App integration
Push notifications
Notify people about support replies through Apple Push Notification service (APNs) on iOS and Firebase Cloud Messaging (FCM) on Android, refresh unread state in the foreground, and open chat when they tap a notification. Keep your app’s existing notification handling and permission flow throughout setup. The iOS steps come first; Android apps follow Push on Android.
How push works with Reception
Complete Get started first. Push needs a correctly signed app, notification authorization, an APNs device token forwarded to the SDK (on Android, an FCM token the SDK fetches itself), and matching credentials in the dashboard. Chat remains usable without notification permission. You can prepare the app hooks now and complete dashboard credentials later. The SDK also refreshes unread state without push; see Automatic unread checks.
Your app owns permission requests, APNs registration, delegate routing, and foreground presentation. The SDK stages the token, synchronizes it after support usage starts, recognizes Reception payloads, and requests chat presentation. The backend sends alert notifications for agent replies, including replies from Telegram, Slack and review cards.
Offer cards push like any other reply. Apple treats those as promotional, so your permission flow must cover them; see Offer pushes.
Link cards push like any other reply too. The preview shows the card message, or the button label when the message is empty.
Push delivery is best-effort. A saved reply or configured key does not prove a notification reached a phone.
Set up Xcode
Open your app target’s Signing & Capabilities and add Push Notifications.
Enable push for your app's identifier in Apple Developer (Apple calls it an App ID) and use a provisioning profile that includes it.
Check the target’s entitlements file and
CODE_SIGN_ENTITLEMENTSmapping. Verify that the signed app hasaps-environment:developmentfor development provisioning orproductionfor distribution. Let signing determine the entitlement.
These steps follow Apple’s APNs registration guide. Reception sends alert pushes; this integration does not require Background Modes → Remote notifications. Dashboard credentials do not replace app signing or entitlements.
Keep permission under your app’s control
The SDK asks for notification permission only through its card in the chat, which you control in the dashboard; it never prompts at launch. Reuse your existing permission timing and UI. Do not add a launch prompt just to integrate Reception. If you plan to send offer cards, say in that permission flow that notifications can include offers (or let the chat card ask with Replies and offers), and give people an in-app way to turn those off; Apple requires both for promotional notifications (guideline 4.5.4). If your app has no permission flow, the chat card can be it; wire the non-prompting hooks below either way. Apple recommends asking in context and checking current settings because people can change their choices. Apple’s authorization guidance.
A previous permission request is not proof of current authorization. After configuring Reception, call its helper at launch, on foreground, after your existing permission flow succeeds, and after logout or successful deletion. It registers with APNs only for authorized, provisional or ephemeral permission, and never prompts:
import Reception
await Reception.shared.registerForPushIfAuthorized()For SwiftUI, merge the following into your existing app view. HomeView represents your existing app content. If your app already performs foreground registration, reuse that flow instead of adding another one. Configure the SDK in your app initializer before these callbacks can run, as shown in Get started.
import SwiftUI
import Reception
struct RootView: View {
@Environment(\.scenePhase) private var scenePhase
var body: some View {
HomeView()
.task(id: scenePhase) {
if scenePhase == .active {
await Reception.shared.registerForPushIfAuthorized()
}
}
}
}Provisional authorization can deliver quietly to Notification Center without a banner or sound. Check the device’s actual settings during verification. Do not treat quiet delivery as a failed APNs request. Apple’s provisional authorization behavior.
Ask for permission in the chat
Reception can ask for notification permission at the moment it matters: right after the person sends a message, a small card appears below it, at the bottom of the chat just above the message field, with Continue and No thanks. Continue shows the system permission dialog. The card is off by default. Turn it on and choose what it says in the dashboard under Settings → your app → Push Notifications → Ask for push notifications; it needs no code beyond the push setup on this page: It works the same in React Native and Flutter apps, since the card is part of the bundled SDK.
| Setting | What the card says |
|---|---|
| Off (default) | Nothing; the SDK never asks. |
| Replies only | “Get a notification when we reply.” |
| Replies and offers | “Get notifications for replies, offers and updates.” |
The texts are fixed. The card stays under the person’s latest message until they tap Continue or No thanks: when your team replies it goes away, and when the person writes again it comes back. There is never more than one. It shows only while iOS has never asked for notification permission for your app. If your app already asked, whatever the answer, the card stays hidden. On Android the card shows on Android 13 and later while the notification permission has never been answered; below Android 13 notifications are allowed without asking, so the card never shows. No thanks is remembered on the device, so the card does not come back. The setting is available once APNs or Firebase is configured in the dashboard. Each platform shows the card only once its own credentials are saved: an iPhone needs APNs, an Android device needs Firebase. The SDK reads the setting along with the chat appearance. The card appears only while remote appearance is on (the default); with usesRemoteAppearance = false the chat shows no card.
Once push works on the device, the same place shows “You’ll get a notification when we reply.” under the person’s latest message. It goes away when your team, the AI assistant or an automation replies, and comes back when the person writes again. It also shows when your app asked for permission itself, whatever the card setting. To hide that line, set Reception.shared.appearance.hidesPushStatus = true (Android: Reception.appearance.hidesPushStatus = true; React Native: appearance.hidesPushStatus; Flutter: ReceptionAppearance(hidesPushStatus: true)), or open Settings → your app → Chat design, select Notification status in the Conversation preview and set it to Hide.
The card does not replace your push hooks. Keep calling registerForPushIfAuthorized() at launch and on foreground, and forward the APNs device token exactly as described below. On Android, keep Firebase Messaging and the message forwarding.
Forward the device token
Reception.shared.setPushToken
Add this call inside your existing app delegate callback. Preserve any forwarding to other notification services. Import UIKit and Reception in that file; the callback and Reception API run on the main actor.
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken token: Data
) {
Reception.shared.setPushToken(token)
// Keep your app's other token handling here.
}Forward every APNs callback, including token changes. Request a fresh token from the system on launch instead of treating an old host-cached token as authoritative. Keep or implement your app’s application(_:didFailToRegisterForRemoteNotificationsWithError:) handler to report registration failures and retry later. Apple’s token lifecycle guidance.
Reception.shared.setPushToken(_ token: Data, environment: Reception.PushEnvironment = .automatic) stages the hexadecimal token and resolved environment locally. Calls before Reception.configure(appId:), empty tokens, and unresolved environments are ignored. The method returns no delivery or synchronization result.
For a registered session that has started support, forwarding promptly starts a device update and unread refresh. Otherwise, the token is sent in a device update right after launch registration (SDK 1.6+), or after the first valid send attempt on older SDKs. Forwarding a token alone does not register a Reception device; launch does. After Reception.shared.logout() clears the staged token, use your registration flow to forward it again. See Login and logout.
Reception.PushEnvironment
| Value | Resolution |
|---|---|
.automatic | Default. Selects sandbox on the simulator. On a physical device, reads aps-environment from the embedded provisioning profile. development selects sandbox; production selects production. No embedded profile selects production. An unreadable profile or missing/unrecognized entitlement causes the token to be ignored. |
.sandbox | Explicit APNs sandbox. Use only for a known development token. |
.production | Explicit APNs production. Use for a known production token, including TestFlight and App Store builds. |
If detection is unavailable for your host, replace the forwarding call in the delegate with an explicit environment only after checking the signing configuration:
Reception.shared.setPushToken(token, environment: .sandbox)Use .production for the corresponding production token. Do not choose an environment from #if DEBUG: build flags do not establish how the app was provisioned. Do not force an override to turn a simulator test into evidence of real-device delivery.
Handle notifications
Reception.shared.handlePushNotification
Reception.shared.handlePushNotification(userInfo: [AnyHashable: Any], openChat: Bool = true) -> Bool is a main-actor method. It returns true when reception.conversationId is a nonempty string, and false for an unrelated or malformed payload.
A true result only means the payload was recognized. It does not validate the conversation against the server, confirm a refresh, or select a historical conversation by that ID. Reception opens the current session’s chat and requests an unread refresh. An old notification after logout cannot restore the previous session.
Use openChat: false for foreground receipt. For taps that open the SDK sheet, keep the default true, including after a cold start. For your own Support tab or navigation destination, pass false and open that destination when the method returns true. See Custom navigation.
Preserve delegate ownership
Merge the next two methods into the object that already owns UNUserNotificationCenterDelegate. Import UserNotifications and Reception there. Keep a single notification-center delegate and preserve unrelated notification handlers, custom actions, analytics, and your existing presentation policy. Do not implement both async and completion-handler variants of the same callback. With completion handlers, call each completion exactly once on every path.
Keep the delegate methods on the main actor: mark the delegate class @MainActor and declare the conformance as @preconcurrency UNUserNotificationCenterDelegate. Never mark these methods nonisolated. UIKit expects the completion of a notification tap on the main thread; a nonisolated async method completes on a background thread and the app crashes when the user taps a notification. If the class cannot be @MainActor, mark both methods @MainActor instead and keep @preconcurrency on the conformance.
If you have no notification delegate, make your existing app delegate conform to UNUserNotificationCenterDelegate and assign UNUserNotificationCenter.current().delegate = self during application(_:didFinishLaunchingWithOptions:). If the SwiftUI app has no app delegate either, connect one with @UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate in the App type. Reuse an existing adaptor when present. Retain a separate delegate object for the application’s lifetime if you use one.
Foreground receipt
Forward the payload with openChat: false. Reception refreshes unread state without opening chat. Present nothing while Support chat is open; otherwise request a banner and sound.
This example belongs in the existing main-actor notification delegate. The final return is an example fallback: preserve your existing policy for other notifications there.
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification
) async -> UNNotificationPresentationOptions {
if Reception.shared.handlePushNotification(userInfo: notification.request.content.userInfo, openChat: false) {
return Reception.shared.isChatOpen ? [] : [.banner, .sound]
}
return [.banner, .sound] // Keep your existing policy for unrelated notifications.
}Notification taps
Forward the tapped payload with the default openChat: true. Reception opens the SDK sheet, including on cold start, and returns whether it recognized the payload. For your own Support destination, pass openChat: false and navigate when the method returns true.
Add this alongside foreground routing in the same delegate. Keep existing custom-action routing when your app uses notification actions; this example handles the ordinary Support tap.
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse
) async {
if Reception.shared.handlePushNotification(userInfo: response.notification.request.content.userInfo) { return }
// Keep your existing routing for unrelated notifications here.
}These examples compile in Swift 5 and Swift 6 language modes, with or without default main-actor isolation. If someone later adds nonisolated, the synchronous Reception call no longer compiles instead of crashing at runtime; restore the main-actor isolation rather than adding await.
App badge and unread refresh
Reception.shared.updatesAppBadge defaults to true. The SDK mirrors its unread count to the app icon. When that count reaches zero, it removes delivered notifications whose payload contains reception. To let your app manage both behaviors, set the following during app initialization on the main actor:
Reception.shared.updatesAppBadge = falseThis disables SDK badge synchronization and notification removal. Registration includes the preference; active support sessions synchronize changes asynchronously and retry after failures and on foreground. After the server saves false, new support pushes omit aps.badge entirely while keeping their alert and configured sound. Offline, the last successfully saved preference remains in effect. Already prepared or delivered notifications are not changed. Set the flag on each app launch; the SDK does not combine host feature counts or clear an existing badge when you change it.
After support usage starts, the SDK refreshes unread state on foreground. Automatic checks pause while push is configured and notification permission is available, and can resume if permission is revoked. Checks stop in the background. See Unread messages.
Configure APNs in the dashboard
As an admin, open Settings → your app → Push Notifications. Open the connection row to enter or edit your credentials. If you need a key, select View setup guide.
Obtain an APNs signing key from Apple Developer → Certificates, Identifiers & Profiles → Keys. Upload the .p8 private key through the Reception dashboard; do not bundle it in the app. Apple provides the key file and its Key ID for token authentication. Apple’s APNs key documentation.
| Dashboard field | Value |
|---|---|
| Bundle ID | The signed app’s bundle identifier, for example com.example.app. Used as the APNs topic. |
| Key ID | The key’s 10-character identifier, uppercase letters and numbers. |
| Team ID | Your Apple Developer team’s 10-character identifier, uppercase letters and numbers. |
| Private key (.p8) | Upload the APNs signing key, at most 16 KB. Reception stores the key encrypted. |
Select Connect, or Save changes when editing. Replace key (.p8) is optional when a key is already saved; leaving it unchanged retains the saved key. Disconnect removes the key after confirmation while retaining identifiers and notification content settings. Saving settings does not send a notification.
Match key and device environments
There is no dashboard environment selector. Reception uses the environment reported by each device. Reception stores one APNs key per app.
Create the key with the environment Sandbox & Production. Development-provisioned builds use Sandbox; distribution-provisioned builds, including TestFlight and App Store builds, use Production. A key limited to Sandbox or to Production only reaches builds in that environment. Apple’s key options.
Configured means credentials are saved. Onboarding does not test delivery. In app settings, choose Send test and confirm arrival on a real device, including after correcting a connection. A reported rejection may remain until a delivery succeeds.
Push on Android
On Android, Reception sends each reply as a high-priority FCM data message to the device’s FCM registration token. The SDK, not Firebase, shows the notification, so it can stay quiet while the chat is open, exactly like the iOS foreground policy. Your app needs Firebase Messaging and its google-services.json; it does not need code that builds notifications. There is no Sandbox or Production environment on Android.
Firebase in your app
If your app does not use Firebase yet, register it in a Firebase project and add Firebase Messaging as shown in the Android guide. Use the same Firebase project whose service-account key you upload in the dashboard. Without Firebase in the app, the SDK logs once at debug level and registers no token; chat and in-app unread counts still work.
Receive Reception’s messages
Choose one of these, depending on whether your app already has a messaging service:
| Your app | What to add |
|---|---|
No FirebaseMessagingService of its own | Enable the SDK’s sh.reception.ReceptionMessagingService in AndroidManifest.xml with the com.google.firebase.MESSAGING_EVENT intent filter. It shows Reception’s replies and registers new tokens while notifications are allowed. |
Its own FirebaseMessagingService | Call Reception.handlePushMessage(this, message.data, message.messageId) first in onMessageReceived and return when it is true; call Reception.setPushToken(token) in onNewToken. Do not also enable the SDK’s service. |
The SDK declares its service without an intent filter, so it receives nothing until you add one. handlePushMessage returns true only for Reception’s messages; your own messages keep their handling. Both snippets are in the Android guide. FCM can deliver a message more than once; the SDK recognizes a repeated FCM message ID, passed as message.messageId, returns true and shows no second notification. Android delivers no message to an app the person force-stopped in Settings until they open it again; an app the system stopped in the background receives messages as usual.
React Native and Flutter on Android
The packages handle Reception’s messages natively, with no forwarding code; your app adds Firebase and its google-services.json:
Flutter (
reception_flutter1.2.0+): add Firebase throughfirebase_messaging, or on the Gradle side only with the Google services plugin andcom.google.firebase:firebase-messaging. Do not add the SDK’sReceptionMessagingService: the plugin receives Reception’s messages beside Firebase, also before any Dart code runs. Withfirebase_messaging, Reception’s messages also reachonMessageand the background handler as data-only messages with areceptionfield; skip them there. Withconfigure(handlesNotifications: false)the plugin shows nothing. See Push on Android in the Flutter guide.React Native (
react-native-reception1.6.0+): setandroid.googleServicesFileand run prebuild. Withexpo-notifications, the module’s subclass of Expo’s messaging service passes Reception’s replies to the SDK and everything else to Expo; without it, the config plugin declares the SDK’sReceptionMessagingServiceand the app addscom.google.firebase:firebase-messaging. With@react-native-firebase/messaging, subclass its service and callReception.handlePushMessage.startReceptionPush()only keeps the FCM token current. See Push on Android in the React Native guide.
In both, the SDK registers the FCM token, shows and hides notifications and opens the chat on taps exactly as described on this page. Nothing APNs-related applies on Android.
Permission and token
On Android 13 and later, notifications need the POST_NOTIFICATIONS runtime permission. The SDK’s manifest declares it. It is requested by your app’s own permission flow or by the chat card; the SDK asks in no other way, and none of the calls below asks. The Android guide shows a short request for apps without a flow. Below Android 13, notifications are allowed unless the person turns them off.
The SDK fetches the FCM token and registers it at configure and whenever the app returns to the foreground, as long as notifications are allowed. A new token that Firebase hands to the SDK’s ReceptionMessagingService is registered under the same rule; one that arrives before the permission is fetched again once it is granted. Reception.setPushToken(token) from your own service registers the token whenever you call it. After your own permission request, call:
Reception.registerForPushIfAuthorized() // Never asks for permission.After logout() or a successful deleteData() the SDK registers the token again for the new session by itself. Forward only FCM tokens, never an APNs token, Expo push token or OneSignal ID.
Notifications and taps
While the chat is open, the SDK shows no notification for a reply; the open chat receives it through its own live connection, and the push only refreshes the unread count. Otherwise the SDK posts a notification on its channel “Support replies” (localized; high importance, so it can appear as a heads-up), grouped per conversation, with sound when Sound is on. People can change the channel in the system settings. Set Reception.notificationSmallIcon to your app’s monochrome notification icon; otherwise the SDK draws a bell. Flutter and React Native name the drawable at configure, as their guides show (Flutter, React Native).
A tap brings your app’s existing task to the front as the person left it, also when Android ended the process and kept the app in Recents, or starts the app when it has no task, and opens the chat over the screen on top, with no code in your app. If your app shows Reception’s notifications itself or routes taps through its own code, pass the message data to Reception.handlePushNotification(data, openChat = true); it opens the chat and refreshes the unread count, and never posts a notification.
Badge
Android has no app-icon badge API. Launchers that show badges take the count from notifications: with Reception.updatesAppBadge on (the default), each Reception notification carries the unread count, and the SDK removes its notifications once the count reaches zero. Set Reception.updatesAppBadge = false at launch if your app manages its notification counts; the service then leaves the count out. The in-app unreadCount is unaffected.
Message data
The service sends these data fields. This is a synthetic example; the backend generates real messages:
{
"reception": "example-conversation-id",
"title": "New message from support",
"body": "Your reply is ready.",
"badge": "1",
"sound": "default"
}reception is the SDK’s recognition marker. badge is present while updatesAppBadge is on; sound while Sound is on. Messages of one conversation share a collapse key. Your notification content settings apply to Android too.
Verify on Android
Install a debug build on a phone or on an emulator with Google Play services, with the
google-services.jsonof the Firebase project whose key is saved in the dashboard.Allow notifications through your app’s flow or the chat card, return to the app, and send a support message.
In app settings, open Push Notifications → Send test, choose the device labeled Android, and send the test.
Background the app, send a dashboard reply, and check the notification and the tap that opens the chat. Repeat with the app swiped away from Recents, with the app in the foreground and the chat closed, and with the chat open (no notification).
With
adb logcat -s ReceptionandReception.logLevel = Reception.LogLevel.DEBUG, the SDK logs when it stages a token, recognizes a message and shows a notification.
Configure Firebase in the dashboard
As an admin, open Settings → your app → Push Notifications and choose Android (Firebase). If you need a key, select View setup guide.
In the Firebase console, open the project your Android app is registered in. Cloud Messaging API (V1) must be enabled under Project settings → Cloud Messaging.
Under Project settings → Service accounts, choose Generate new private key. Firebase downloads a
.jsonfile; keep it private and never bundle it in the app.Upload the file as Service account key (.json), or paste its contents, and select Connect. The file can be at most 16 KB. Reception stores it encrypted and shows the project ID and service-account email.
Replace key (.json) is optional when a key is already saved. Disconnect removes the key. The Package name shown there is your app’s applicationId; it is saved with Review requests and used for Google Play review links. Configured means the key is saved; choose Send test to check delivery. When FCM reports a token as no longer registered, Reception clears it from the device; other rejections show as Push issue in device details.
Offer pushes
Every offer card sends a push, whether a teammate, the AI assistant or an automation sends it. There is no dashboard switch; the app needs the APNs or Firebase setup above.
Apple treats offer pushes as promotional. Before you send offers, your app must get explicit consent, saying that notifications can include offers, and provide an in-app way to opt out (guideline 4.5.4). The chat card set to Replies and offers asks with that wording; the opt-out is up to your app. Offer cards a teammate or the AI assistant sends still push like replies. Reception cannot check this for you. Until your app asks for that consent, send replies and review requests only.
The preview uses the card message, or the chosen custom button label when the message is empty. With neither, it uses “See your discount” in the customer's language. Your notification templates, Show message, and Sound settings also apply. Turning off Show message replaces the preview with a generic prompt.
Customize notification content
In app settings, open Push Notifications → Notification content. The content applies to iOS and Android. Choose a preview language and select Customize to edit Title, Message, and Sender name. The preview uses a two-photo example and does not send a push.
Show message
Enabled by default. Reply text becomes the preview; text with photos gets a photo marker, and photos without text get a localized photo summary. Turning this off replaces the reply placeholder with a localized prompt to read the reply, including inside custom templates. The actual chat message is unchanged. See Privacy and data.
Sound
Enabled by default. When enabled, the payload includes sound: "default"; when disabled, it omits that field. Actual presentation also depends on iOS settings and your foreground delegate policy.
Title and Message
Overrides apply to the selected language only, with a maximum of 120 characters per template. Spaces count toward the limit. Blank or default-equivalent fields use built-in text. The Insert menus provide these substitutions:
| Variable | Meaning |
|---|---|
{message} | Reply preview or localized hidden-message prompt, depending on Show message. |
{agent} | Global Sender name, or the localized Support default. It is not the replying agent’s profile name. |
{app} | The app name saved in Reception. |
Rendered titles are capped at 100 characters and bodies at 500 characters. Empty rendered titles fall back to the app name; empty bodies fall back to the message placeholder. Reset text to default clears the selected language’s title and message overrides. Save commits edits; Cancel discards them.
Sender name
One optional name shared by all languages, trimmed and limited to 60 characters. Clearing it restores the localized default. Setting it changes the default title to include the sender; custom titles only include it when they use {agent}.
Notification language
Delivery uses the device’s last successfully reported app language, matched to a supported language or English. Device locale is used only for older devices without an app-language report. Custom templates are not automatically translated. Changing Preview language edits/previews translations; it does not change a customer’s language. See Language for all supported codes and host-app language synchronization.
Payload shape
The backend sends the following shape. This JSON is a synthetic example for understanding delegate routing, not proof of delivery. Put equivalent test data in your own notification test fixture if needed; the backend generates real payloads automatically.
{
"aps": {
"alert": {
"title": "New message from support",
"body": "Your reply is ready."
},
"badge": 1,
"sound": "default",
"thread-id": "example-conversation-id"
},
"reception": {
"conversationId": "example-conversation-id"
}
}aps.thread-id groups notifications for the conversation. reception.conversationId is the SDK recognition marker. Sound is optional. When the device’s last saved updatesAppBadge preference is true (the default for older clients), the badge carries the conversation’s unread-for-user count. With false, aps.badge is omitted, including when the count is zero.
Verify on a real device
Install a correctly signed build on your iPhone. Confirm the bundle ID, push entitlement, and signing environment.
Grant permission through your app’s existing intentional flow. Return to the app so the foreground check registers with APNs. Confirm the delegate forwards a nonempty token after configuring the SDK; do not publish the token in logs or screenshots.
Send a support message from the phone. This registers the Reception device, uploads its staged push information, and creates a conversation.
Save the matching APNs credentials. In app settings, open Push Notifications → Send test, choose the Device, and select Send test. Labels include Sandbox or Production. The selector lists up to ten eligible devices ordered by recent chat activity; use your test device recently if it is missing.
Observe the notification on the phone. A successful test action means APNs accepted the request, not that the notification was displayed. Tests use saved content settings and an existing conversation; they do not create a chat message.
Background the app and send a real dashboard reply. Confirm arrival, tap the notification, and verify chat opens and displays the reply. Repeat a tap when the app is not running to check launch routing.
Repeat with the app foregrounded and chat closed, then with chat open. Check unread refresh and the intended banner/sound policy. Confirm unrelated notifications retain their behavior.
Test development and distribution builds separately with compatible credentials. Also test denied permission, re-enabling permission in Settings, and forwarding again after logout.
Troubleshooting
| Symptom | Check |
|---|---|
| No APNs registration callback | Check push capability, signed entitlements, network access, and didFailToRegisterForRemoteNotificationsWithError. Recheck current permission in your registration helper. |
| No eligible device in Send test | Use a real iPhone, forward its token after configuration, and send a support message. A device registers at launch, whether or not the chat is used. Refresh app settings after synchronization. |
| Token is ignored | Check for an empty token, calls before configuration, simulator automatic mode, and unreadable/missing profile entitlements. Forward again after logout. |
| BadDeviceToken or environment rejection | Compare Sandbox/Production with provisioning. Correct explicit overrides and ensure the signing key permits that environment. |
| Topic or credential rejection | Check Bundle ID against the signed app, Key ID against the uploaded key, Team ID, key scope, and revocation status in Apple Developer. |
| Configured but nothing arrives | Confirm the device has a conversation and token, credentials match its environment, and notification settings permit the expected presentation. Check Notification Center for quiet delivery. |
| APNs records a rejection | Inspect Push issue in device details. Check the reason against your Apple credentials, bundle ID, and device environment, then send a test or reply after correcting it. Contact Reception if it persists. |
| No rejection shown despite failure | Confirm credentials and device setup, then test delivery. An empty Push issue field does not prove success. |
| Tap does not open chat | Configure before callbacks and preserve delegate routing. Use openChat: true for the SDK sheet, or false and your own navigation for a host-owned chat. |
| Swift concurrency diagnostics | Extract the conversation ID before the actor hop. Rebuild the minimal dictionary on the main actor instead of transferring the original notification or payload. |
| Unexpected badge changes | Review Reception.shared.updatesAppBadge and your delegate options. The server omits the APNs badge field only after the preference is successfully synchronized; offline or already prepared pushes can still use the previous value. |
| Android: no notification | Check that the Firebase project of the app’s google-services.json matches the uploaded key, that exactly one messaging service receives FCM (yours forwarding to handlePushMessage, or the SDK’s), that notifications and the “Support replies” channel are allowed, and that the app was not force-stopped. |
| Android: no eligible device in Send test | Check that Firebase Messaging is in the app and notifications are allowed, then return to the app and send a support message. With debug logs on, Logcat shows when the SDK stages the token. |
| Android: a tap opens the app but not the chat | Native apps: check that Reception.configure runs in Application.onCreate. Flutter and React Native: check that configure runs at startup, not only after a later screen, and (Flutter) without handlesNotifications: false. If your app shows Reception’s notifications itself or routes taps itself, pass the data to Reception.handlePushNotification(data). |
| Permission is denied | Respect the decision. Use your existing settings flow and recheck on foreground; do not introduce repeated permission prompts. Chat still works. |
For broader networking and integration issues, see Troubleshooting and the SDK reference.