Get started
Get started
Add Reception to your native iOS or Android app, or your React Native or Flutter app, send your first message, and reply from the dashboard. One setup prompt detects your project and guides the integration.
Requirements
An iOS 17 or later app, using SwiftUI, UIKit, React Native, Expo or Flutter, or an Android 7.0 (API 24) or later app, using Jetpack Compose, Views, React Native, Expo or Flutter. Android support in the packages arrives with
react-native-reception1.6.0 andreception_flutter1.2.0; earlier versions run on iOS only.iOS: Xcode 26. Native iOS uses Swift Package Manager; Flutter uses Swift Package Manager or CocoaPods.
Android: Gradle with Android Gradle Plugin 8 or 9 (tested with AGP 8.9 and 9),
compileSdk35 or later and Kotlin 2.0 or later. The SDK comes from Maven Central; the React Native and Flutter packages bring it themselves.React Native and Flutter, on both platforms: React Native requires Expo SDK 54+ (verified 54–57; Android also on Expo 58), its default React Native/React versions, and a development build, not Expo Go. Bare React Native needs Expo Modules. Flutter requires Flutter 3.44+ (verified on 3.44 and 3.47) and Dart 3.12+.
A Reception dashboard account with permission to create an app.
The Swift SDK has no package dependencies; the Android SDK uses AndroidX, Jetpack Compose, OkHttp and Coil, and Firebase Messaging and Google Play Billing only when your app has them; the React Native wrapper uses Expo Modules, and the Flutter plugin includes the Swift sources; on Android both depend on the Android SDK. Your app does not need user accounts or push notifications for its first conversation.
Create an app in the dashboard
Sign in and choose Add your app, or Settings → Add app.
Enter your app's name and create the app.
On Connect, choose Copy setup prompt for a coding agent or Set up manually for the platform guides and code snippets. Both contain your app's configuration.
For an existing app, open Settings → your app → SDK Setup for the same setup options, even after connecting. Its permanent App ID is also available under General.
The App ID starts with app_ and is safe to include in your app. It's the only configuration your app needs.
Set up with a coding agent
Your coding agent adds the SDK to your app, fits it into your app's design and flows, and checks that messages arrive. You start with two questions.
Choose Copy setup prompt in the dashboard. The prompt contains your App ID.
Paste it into your coding agent, such as Claude Code, Codex or Cursor, with your app project open. The agent reads the linked guides during setup.
Answer the agent's two questions.
If you like, reply to the first message right from the Reception setup; your reply shows up in the app as an unread badge.
Go through the design round: the agent shows screenshots of the Support entry, the welcome screen and the chat, and changes what you'd like different.
If your app has sign-in and a backend, choose whether to add identity verification now or later.
Read the agent's short result and continue in the dashboard under Integrations.
A coding agent with only this page follows the setup prompt below and asks you for the App ID.
The two questions
Where Support goes. The agent recommends a Support entry on your home screen plus a row in Settings, in your app's style. If your app already has a contact option, it asks whether Support should replace it. The entry is your app's own code, so it can look and sit wherever you like.
What your team sees about each user. The agent lists details it found in your app, such as the plan, sign-up date or number of projects. Pick any, name others, or choose none. They show next to each chat.
What the agent does by itself
Adds the package and configures it with your App ID.
Adds a line with the docs link to your project's
AGENTS.md, and toCLAUDE.mdif you have one, so later agent sessions know where to look.Matches the chat to your app's colors, font, and light or dark mode, and connects your in-app language setting if there is one.
Builds the Support entry as a copy of a control your app already has, with unread badges on it and on the rows that lead to it, and on one tab.
Connects sign-in, sign-out and account deletion if your app has accounts, and shows a name your users entered even without accounts.
Adds push handling without adding a permission prompt of its own. Once your app has permission and you've uploaded your APNs key (iOS) or Firebase key (Android), replies arrive as notifications. If your app never asks, you can let the chat ask after the person writes.
Connects your paywall to paywall cards if your app has one.
Builds the app and runs the setup check: the app sends "Hello from setup" from a simulator or Android emulator, and the message appears in your inbox. It's a real message and counts as your app's first conversation.
The design round
After the setup check, the agent goes through three looks with you, one at a time: the Support entry, the welcome screen and the chat. For each it shows a simulator or emulator screenshot and asks whether it fits. It can change the entry's look, the welcome icon (for example your photo, with size and rounding), the welcome title and text in every language your app supports, hide parts, and adjust colors and font. Your team's photos and first names next to replies are switched on in the dashboard under Settings → your app → Appearance; the agent explains where. Say "fits" to move on.
Identity verification (optional)
After the design round, the agent offers identity verification if your app has user sign-in and a backend, including Firebase or Supabase. Your backend confirms which signed-in account a chat belongs to, so your team can trust its user ID. Without verification, app-supplied identity shows as Unverified.
Choose now and the agent follows the verification guide to connect your backend and app. You store the secret on your server; it never goes in your app or agent chat. Choose later to finish setup; Settings → your app → Identity Verification has its own setup prompt whenever you're ready. Apps with only guest or anonymous IDs skip this question, as do apps that already have verification.
Your steps afterwards
Integrations: set up Push, so users notice replies, and if you like Slack, Telegram and Reviews. Then tell your agent "test push" to check a notification on the simulator or emulator. See Push notifications.
Store privacy: update your app's privacy details in App Store Connect, or the Data safety form in Google Play Console. Your agent can list what to select; see App Store privacy and Google Play data safety.
Change it later
Tell your coding agent, for example "Move Support to the profile screen", "Use our secondary color in the chat" or "Also show the user's plan". The docs link next to Reception.configure and in your project's AGENTS.md leads agents in later sessions to the right page.
You can also change the chat's colors and welcome text without an app update under Settings → your app → Appearance. See Remote appearance.
Setup prompt
The dashboard copies this prompt with your App ID filled in.
Integrate Reception, a native in-app support chat, into this app.
App ID: not included. Ask the developer for it along with the questions in step 2 (dashboard: Settings → your app → General) and use it wherever app_YOUR_APP_ID appears. Never ship the placeholder.
Docs for agents: https://reception.sh/llms.txt (every page is also Markdown at https://reception.sh/docs/<page>.md)
Work through the steps in order. Keep the app's code, style and flows; change only what the integration needs. Keep every message to the developer to a few short lines, with one question at a time. Suggested answers are fine, but the developer must always be able to answer in their own words; if a form can't take a free answer, ask in a plain message.
## 1. Understand the app
First select the intended app and its workspace. If several app targets could match the request, ask which one to integrate before editing. Inspect that app’s own manifest, not another app’s or the repository root’s: a package.json with react-native or expo in dependencies or devDependencies means React Native/Expo; a pubspec.yaml with flutter: in its dependencies means Flutter; otherwise a build.gradle or build.gradle.kts that applies com.android.application means native Android (Kotlin or Java, Jetpack Compose or Views); otherwise use native iOS (SwiftUI or UIKit). Follow only that platform’s instructions below. Reception supports iOS 17+ and Android 7.0 (API 24)+. The React Native and Flutter packages run on Android from react-native-reception 1.6.0 and reception_flutter 1.2.0 (earlier, their Android calls are no-ops, as web and desktop calls always are); cover the platforms the project builds for (ios/, android/). Inspect the app target, startup code, navigation (tabs, settings, menus), theme (color assets, theme types, custom fonts, fixed light or dark mode), sign-in, its backend or auth provider, account deletion, notification handling, an in-app language setting, paywall code, and any existing contact or feedback path.
## 2. Ask two questions, then wait
Ask both in one message with your recommendations and wait for the answers. Everything else up to the design round happens without asking.
a) Where should Support go? Recommend a Support entry on the home screen plus a Support row in Settings: the home screen brings the most feedback early, and it can move anytime. Describe the concrete plan (screen, which existing control it copies and from where, icon only or icon with label) and invite changes. If the app already has a contact or feedback path, point it out and ask whether Support should replace it.
b) Which user details should the team see next to each chat? List concrete fields you found that help support, for example plan, sign-up date or counts of the app's main objects. Reception already shows app version, device, OS, language, region and push status, so skip those. If the app stores the user's name or email, say it will show next to each chat. If the app sells subscriptions, its paywall file below sends plan (product ID), status and renewal or expiry date; offer them as fields. The developer picks, names others, or says none. Never propose health data, passwords, precise location or payment details.
## 3. Add the package and configure
Native iOS: add https://github.com/reception-sh/reception-ios.git (from 1.7.1, up to next major), product Reception, to the app target; for XcodeGen or Tuist, edit the manifest and regenerate. Configure once at launch on the main actor in the existing App initializer (UIKit: application(_:didFinishLaunchingWithOptions:)). Follow https://reception.sh/docs/native-ios.md for configuration, appearance, entry, accounts and push code.
Native Android: add sh.reception:reception:1.0.0 from Maven Central to the app module as the Android guide’s Install section shows. Configure once in Application.onCreate, adding an Application subclass if there is none. Follow https://reception.sh/docs/android.md for configuration, appearance, entry, accounts, push and paywalls code.
React Native/Expo (Expo SDK 54+, verified 54–57; Android also on Expo 58): run npx expo install react-native-reception. Add its config plugin to the existing app config and apply it with npx expo prebuild for the platforms the project builds (--platform ios, --platform android; no Gradle or manifest edits); bare React Native needs Expo Modules. Await configure once in the existing app startup before identity or chat. Follow https://reception.sh/docs/react-native.md for configuration, appearance, entry, accounts, push and paywalls code. Use a development build; Expo Go is unsupported.
Flutter (Flutter 3.44+, verified on 3.44 and 3.47, Dart 3.12+): run flutter pub add reception_flutter; never add the native Reception Swift package as well. New Flutter projects target an iOS version below 17, so raise the deployment target to 17.0 as the Flutter guide’s Install section describes and tell the developer that devices below iOS 17 then can't install the app. Android needs no Gradle or manifest edits, except raising a minSdk below 24 to 24 as the same section describes, telling the developer. Await configure once in main() before identity or chat. Follow https://reception.sh/docs/flutter.md for configuration, appearance, entry, accounts, push and paywalls code.
The iOS paths need iOS 17+ and Xcode 26, the Android paths minSdk 24+ (native Android also compileSdk 35+); apart from the Flutter step above, report an older deployment target or SDK level instead of changing it. Use App ID app_YOUR_APP_ID in the selected guide’s configure call. Add a comment next to it: "Reception support chat. Docs for changes: https://reception.sh/llms.txt". Read the linked guides before implementing; if unavailable, report the blocked parts instead of guessing APIs.
Add this line to AGENTS.md at the project root (create the file if there is none) and, if the project has a CLAUDE.md, to that too, so later agent sessions find the docs:
```markdown
- Reception support chat: before changing or debugging it, read https://reception.sh/llms.txt and the page it links for the task. If the docs are unreachable, work from the Reception package source and say what you couldn't verify.
```
Right after configure, match the chat to the app:
- Set the selected SDK’s appearance accentColor, onAccentColor, chatBackground, incomingBackground and incomingForeground from the app's own colors, and fontFamily from its custom font. Read them from its color assets or theme type, so light and dark mode follow the app (native Android: ReceptionColor light/dark pairs or resources, as its guide shows), and set them again when the app's own theme setting changes. Never hardcode or invent colors; leave an option unset when the app has no matching color.
- If the app is always dark or always light, or has its own light/dark setting, set preferredColorScheme from it.
- The chat follows the app's language by itself. Only if the app has its own in-app language setting, set languageOverride from it and update it when it changes. On Android, an app that declares no android:localeConfig gets the chat in the phone's language: declare the app's languages as https://reception.sh/docs/language.md (On Android) shows.
- Keep the chat's own texts for now; they are localized in 48 languages, and the design round offers changes.
## 4. Add the support entry
Build the entry the developer chose as a copy of an existing control on that screen: the same component, size, shape, colors, font and icon style. Next to round icon buttons, add a round icon button; where buttons carry text, use icon and label; in Settings, a row like its neighbors. If that screen has no comparable control, copy the closest one elsewhere in the app. Add no new colors, shadows or shapes, and don't fall back to a plain tinted button. Use the selected guide’s openChat call and unread observation; localize its label through the app's strings; when adding keys to an existing strings file, don't reformat or reorder it. Show the live unread count on each entry and on every menu row on the way; hide badges at zero. Style them like the app's existing badges; without any, use Material 3's Badge on Android (Views: BadgeDrawable) and the iOS look on iOS: a system red capsule with the white count centered, on a button's straight top edge just before its top-right corner rounds, at the top right of round icon buttons, at the trailing end of list rows and row-style cards (before a chevron, if there is one), no shadow. Badge only one tab (using the app’s tab badge API): the one with the main entry, such as the home tab. Badges on several tabs count one reply twice.
## 5. Connect what the app already has
Name without sign-in: if the app stores a name the user entered (onboarding, profile, settings), call identify with no user ID and that name at launch and when it changes. Look for it even when the app has no accounts. Names and emails go only through identify, never into setMetadata. A sign-in that stores only a name on the device, without an account, counts as a name without sign-in: identify with that name, and no logout.
Accounts, only if users sign in to the app, with or without a server (skip anonymous or guest IDs the app creates by itself):
- After restoring a signed-in session and after sign-in: identify with the user ID, name and email the app knows and no value for the rest; no placeholders.
- Wherever the app ends a signed-in session (sign-out, account switch, a session found expired at launch): call logout, before the next user's identify. Never when nobody was signed in, such as a guest at launch or before a first sign-in: it starts a new, empty chat.
- On account deletion: await deleteData() before discarding the session; on failure keep the session, show the app's error UI and allow retry.
- logout() and deleteData() also clear the user details and the push token: send the user details again with the next identify, and register for push again if already authorized.
User details: send the fields chosen in 2b with setMetadata (string values, up to 20), and again when they change. Each call replaces all fields, so set them in one place.
Push, always: use the selected platform guide’s helpers once, preserving existing delegates and services and avoiding duplicate Reception listeners. Never request notification permission or add a Reception permission prompt; the SDK can ask inside the chat if the dashboard turns that on. Keep other providers, notification routing and foreground presentation working. If the app owns its icon badge or notification counts, set updatesAppBadge false at launch.
- iOS paths: register at launch, foreground and after the app’s existing permission flow, only when already authorized (including provisional or ephemeral). Forward the raw APNs device token, never an Expo push token, FCM token or OneSignal ID. Forward received notifications with openChat false and tapped notifications with openChat true, including cold starts. Suppress Reception banners while chat is open. On native iOS, keep the notification-center delegate methods on the main actor and never mark them nonisolated; that crashes the app on every notification tap. Add the Push Notifications capability when signing allows. Flutter: the plugin handles push natively; add only what the Flutter guide’s push section lists.
- Android paths use FCM, with nothing APNs-related; the SDK shows Reception’s notifications and opens chat on taps by itself. Native Android: if the app has its own FirebaseMessagingService, forward Reception’s messages and token from it as the Android guide’s Push section shows; otherwise enable the SDK’s ReceptionMessagingService in AndroidManifest.xml. Never both. Flutter and React Native: follow the package guide’s Push on Android section (React Native: its table for expo-notifications, React Native Firebase or neither); never add the SDK’s ReceptionMessagingService or forwarding beyond it yourself (what the package’s config plugin declares stays). Make existing firebase_messaging handlers (onMessage, onBackgroundMessage) skip messages whose data has a reception field. After the app’s existing permission flow, call the nonprompting push refresh the guide names. If the app has no Firebase and no google-services.json yet, don’t add them now; chat and in-app badges work without them, and the wrap-up names it. If the app has a monochrome notification drawable, pass it as notificationSmallIcon as the guide shows.
Paywall cards, only if the app has a paywall. Choose by where the paywall is built, not by what processes purchases, and copy the matching file from https://reception.sh/docs/paywalls.md unchanged apart from its placeholders (and, for ReceptionStorePaywall in React Native, the store calls named below):
- RevenueCat paywall builder: ReceptionRevenueCatPaywalls (.swift for native iOS, .ts for React Native, reception_revenuecat_paywalls.dart for Flutter), then start(), which sends plan, status and renewal or expiry date as user details. React Native and Flutter: each offering with a published paywall needs offering metadata reception: true in RevenueCat; tell the developer, since without it no card opens.
- Superwall, also with RevenueCat for purchases: ReceptionSuperwallPaywalls (.swift, .ts or reception_superwall_paywalls.dart), then start (React Native: mount its hook) with every placement the app registers, each with a title the team recognizes; it sends plan, status and renewal or expiry date as user details.
- Adapty’s Paywall Builder: ReceptionAdaptyPaywalls (.swift, native iOS; React Native and Flutter use ReceptionStorePaywall with Adapty’s SDK), then start(placements:) with every placement ID the app uses, which sends plan, status and renewal or expiry date as user details.
- The app's own paywall screen, with any store library or none: ReceptionStorePaywall (.swift, .ts or reception_store_paywall.dart), pointed at that screen and its product IDs, then start(), which sends plan, status and renewal or expiry date as user details. In React Native the file reads RevenueCat customer info; if the app uses another store library (such as Adapty), replace those RevenueCat calls with that library’s entitlements, subscription dates and purchase-change listener as paywalls.md describes. Flutter: copy reception_store_paywall.dart unchanged apart from its products, then wire ownedProductIds (and optionally purchasesChanged and subscriptionMetadata) to the app's store library as the page shows, or to an empty set without one. Never add RevenueCat for Reception.
- Native Android has no paywall file yet: follow the Android section of paywalls.md. Register each paywall in Reception.paywalls with a title the team recognizes and its source, present it from Reception.onPaywall after calling Reception.closeChat() (the chat sheet is its own activity, so a paywall shown without closing it opens underneath), and call Reception.refreshPaywalls(invalidate = true) when a purchase changes. Send plan, status and renewal or expiry date with setMetadata only if the developer chose them.
With any of these files: if the developer chose other user details too, or declined these, disable syncsSubscriptionMetadata as the selected file shows and merge only the chosen fields from the file's subscriptionMetadata into one setMetadata call, as "Your own metadata" in paywalls.md shows.
Start it (React Native Superwall: mount its hook) after Reception and the vendor are configured. With RevenueCat, complete Reception’s logout or identify before Purchases.logIn or logOut; with Adapty, before Adapty.identify or Adapty.logout. Follow the selected file’s account-switch and refresh instructions.
Leave identity verification for step 8; preserve it if already implemented.
## 6. Build and check
Build and check each platform this machine can build (iOS needs macOS with Xcode); for the other, make the source changes, skip its build and check, and say so in the result.
Native iOS: build the app’s scheme with xcodebuild in Debug for an installed iOS simulator. React Native/Expo: use npx expo run:ios --device "<simulator name>", open its development server once and keep Metro running; the React Native guide covers a build-only fallback. Or use the existing Expo development-build workflow; bare React Native can build its iOS workspace with xcodebuild in Debug. Expo Go cannot run this check. Flutter: if xcrun simctl list devices booted shows none, boot one with xcrun simctl boot <device>; run flutter build ios --simulator --debug, then install build/ios/iphonesimulator/Runner.app with xcrun simctl install; the bundle identifier is PRODUCT_BUNDLE_IDENTIFIER of the Runner target. Android: use an emulator or device from adb devices; if none runs, start one with emulator -avd <name> (names from emulator -list-avds), preferably a Google Play image. Native: ./gradlew :app:assembleDebug (the app module’s debug variant); Flutter: flutter build apk --debug (build/app/outputs/flutter-apk/app-debug.apk); React Native: npx expo run:android, keeping Metro running.
On the iOS paths, use normal simulator signing (without signing, the chat can’t use the Keychain and the check fails). Fix errors and warnings you introduced. Install and launch the built app below. The same native SDK contains the setup check in Debug simulator builds and debuggable Android builds, and on iOS both previews; for React Native and Flutter, let the JavaScript or Dart startup finish configuring Reception before reading the result:
```sh
xcrun simctl install <device> <path to the built .app>
xcrun simctl launch --terminate-running-process <device> <bundle identifier> -ReceptionSetupCheck app_YOUR_APP_ID
xcrun simctl spawn <device> log show --last 2m --info --style compact --predicate 'subsystem BEGINSWITH "com.reception"'
```
On Android (all three paths), <package> is the applicationId; pass -n the last line of adb shell cmd package resolve-activity --brief <package> as printed (the short <package>/.MainActivity form fails when the Gradle namespace differs); with several devices attached, add -s <serial> to every adb command:
```sh
adb install -r <path to the debug .apk>
adb shell am start -S -n <package>/<launcher activity> --es ReceptionSetupCheck app_YOUR_APP_ID
adb logcat -d -s Reception
```
Repeat the log command every 10 seconds, for up to 70 seconds, until a setup check result appears after this launch. "Setup check passed" means Reception received the message "Hello from setup"; it shows in the dashboard inbox and counts as the app's first message. On "Setup check failed: <reason>", fix the cause and run it again: app_id_mismatch (a different App ID is configured), send_not_allowed (sending is blocked), not_delivered (the SDK's log lines before it name the reason), app_not_active (the app didn't reach the foreground), timeout. If you can't run a simulator or emulator or no result appears, say so; never report the check as passed.
When it passes, send this before anything else, in the developer's language: "✓ Your first message arrived in Reception. You can reply to it right from the Reception setup; I'll continue meanwhile." Don't wait for the reply; it shows as the unread badge in the design round.
## 7. Design round
Go through three looks with the developer, one at a time. For each, launch the app on the simulator or emulator, wait a few seconds for it to load, take a screenshot (xcrun simctl io <device> screenshot <file>; Android: adb exec-out screencap -p > <file>.png), show it and ask whether it fits or should look different. Apply changes, rebuild and show a new screenshot until the developer says it fits, then move on.
a) The Support entry: screenshot the screen with the entry. If the developer replied, the reply shows as its badge, which proves replies reach the app. If the entry sits behind onboarding, sign-in or a paywall, ask the developer to tap through once in the simulator and tell you, then take the screenshot.
b) The welcome screen: launch with -ReceptionPreview welcome. Mention in one sentence what can change: the icon (an own image or the founder's photo, with size and rounding), the title and text (for example a personal note from the founder), or hiding any of them.
c) The chat: launch with -ReceptionPreview conversation, which shows example messages; "Alex" is an example teammate, and their name and initial show only while team names or photos are on. Mention in one sentence what can change: colors, font, light or dark mode and the close button. Also explain that replies can show the teammate's photo and first name: turn on Show team photos and Show team names at the dashboard under Settings → your app → Appearance, and upload the photo in the profile at https://reception.sh/settings.
```sh
xcrun simctl launch --terminate-running-process <device> <bundle identifier> -ReceptionPreview welcome
```
Android has no previews, so do c) before b): for c), tap Support (adb shell input tap, coordinates from adb shell uiautomator dump, or ask the developer) to show the setup conversation (it holds only the setup message; the team's bubble shows once someone replies from the dashboard); for b), screenshot the welcome screen only if the developer agrees to adb shell pm clear <package> (it signs the app out and deletes this install's support chat, so a reply sent afterwards no longer reaches it), otherwise describe the options.
The previews open the chat with local example data in Debug simulator builds; they send and save nothing. Make look changes in code with the options the installed SDK version offers (check the docs and the package source). Put new texts in the app's strings file in every language the app supports.
## 8. Offer identity verification
Only offer this if the app has real user sign-in and a backend that can sign tokens (including Firebase or Supabase), and verification isn't already implemented. Skip apps with only guest or anonymous IDs. Ask in the developer's language: "With identity verification, your backend confirms which signed-in account a chat belongs to, so your team can trust its user ID. This requires a backend change and a secret stored there. Would you like to set it up now or later?" Wait for the answer.
If later, point to Copy setup prompt at Settings → your app → Identity Verification and continue to the wrap-up. If now, read the identity verification guide at https://reception.sh/docs/accounts.md and follow its server instructions, including token refresh and account-switch handling; use the selected platform guide for SDK calls and identityRejected events. Keep the sign-out and account-deletion hooks from step 5. If the backend code is elsewhere, ask where it is before editing it. If you can't read the guide, leave verification pending with the dashboard link and continue to the wrap-up.
Have the developer reveal the secret at Settings → your app → Identity Verification and store it on their server as RECEPTION_IDENTITY_SECRET, following Add it to your server. Never ask them to paste it into the chat or put it in the app. Leave Only verified users can chat unchanged. Build after the changes and explain any remaining secret or deployment steps. Once those are done, have the developer sign in and send a support message; verify the Verified badge on that conversation in Reception, asking them to confirm it if you can't inspect it. Report whether verification was observed, confirmed by the developer, or is still pending.
## 9. Wrap up
End with one short message:
- A result line with only what you saw yourself: build, first message, reply in the app (only if a badge showed), design, user details, paywall cards. Mark what failed or what you couldn't check.
- If identity verification was chosen, its result and any remaining steps, distinguishing your own checks from the developer's confirmation.
- That they can continue in the app’s dashboard settings (Settings → your app), one line each, without instructions since the dashboard guides them: Push Notifications, so users notice replies (iOS: with the Bundle ID and Team ID from the project; Android: Android (Firebase), with a service-account key from the app’s Firebase project and the applicationId as package name, plus, without Firebase in the app yet, its google-services.json and Firebase Messaging as the guide’s Android push section shows); Slack or Telegram, to get every message there and reply from it; Review Requests, to ask happy users for an App Store or Google Play review (with the App Store ID, or the applicationId as the Google Play package name, if the project contains it).
- Once push is set up, they can say "test push": then make sure the app has notification permission through its own flow (ask the developer to allow it in the simulator if needed; on Android without such a flow, ask them to allow notifications for the app in Android's settings, or with their OK run adb shell pm grant <package> android.permission.POST_NOTIFICATIONS, then open the app once so the token registers, and after a fresh install send a message from the chat first), send it to the background by launching Settings (xcrun simctl launch <device> com.apple.Preferences; Android, on a Google Play emulator: adb shell input keyevent KEYCODE_HOME), have them reply from the dashboard and screenshot the notification. Report push as working only when one arrived. If the app never asks for notification permission and Ask for push notifications is Off in the dashboard, say that replies then only show inside the app and that the simulator or emulator shows no notification without permission, and don't add a permission prompt.
- Android, only if you set no notification icon: Reception’s notifications show a bell until they add a monochrome drawable, as the guide’s Android push section shows.
- Remaining: the App Store privacy details or, on Android, Google Play’s Data safety form, offering to list what to select (https://reception.sh/docs/privacy-and-data.md, sections App Store privacy and Google Play data safety), and the commit, which is theirs.
- That they can change anything later by telling you, and the chat's look without an app update in the dashboard under Settings → your app → Appearance.
Never put secrets, tokens or customer data in a message. Keep changes focused, add only dependencies required by the selected integration, preserve existing work, and leave commits to the developer.Set up manually
For React Native or Expo, follow React Native; for Flutter, follow Flutter. For Android, see Android below. The instructions below use native Swift.
Add the package
In Xcode, choose File → Add Package Dependencies and enter:
https://github.com/reception-sh/reception-ios.gitKeep the dependency rule Up to Next Major Version and add the Reception library to your app target.
Configure your existing app
Configure once in your existing SwiftUI App initializer, keeping your current root view and other startup work. Replace app_YOUR_APP_ID with your App ID; Set up manually in the dashboard shows this snippet with it filled in.
import SwiftUI
import Reception
@main
@MainActor
struct MyApp: App {
init() {
Reception.configure(appId: "app_YOUR_APP_ID")
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}ContentView() represents your existing root view. Configure once at launch, before using support, and keep SDK calls on the main actor. For an existing UIKit app, follow UIKit integration.
Add a visible entry point
Place this button in your existing settings screen or another chosen SwiftUI view, and import Reception in that file:
Button {
Reception.shared.openChat()
} label: {
HStack {
Text("Support")
Spacer()
if Reception.shared.unreadCount > 0 {
Text("\(Reception.shared.unreadCount) unread")
.foregroundStyle(.secondary)
}
}
}openChat() presents the chat sheet. The unread count updates the view automatically. Adapt the label and badge to your app's styling and localization. See Open & close the chat for other placements and presentations.
If your app manages its own icon badge, set Reception.shared.updatesAppBadge = false at launch. Your in-app support badge still works.
Android
Add the dependency to the app module’s build.gradle.kts and sync Gradle:
dependencies {
implementation("sh.reception:reception:1.0.0")
}Configure once in your existing Application.onCreate; Set up manually in the dashboard shows this snippet with your App ID filled in:
import android.app.Application
import sh.reception.Reception
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
Reception.configure(this, "app_YOUR_APP_ID")
}
}If the app has no Application subclass, register this one with android:name=".MyApplication" on <application> in AndroidManifest.xml. Then call Reception.openChat() from a Support button and collect Reception.unreadCount for its badge; Android shows both for Compose and Views.
Development builds
Simulator, emulator and device builds connect to the hosted service with ordinary internet access. A separate app in the dashboard keeps test conversations apart from customer messages.
Send your first message
Run your app and open Support.
Send
Hello from setupand wait for Sent, or its localized equivalent, below the message.Open that conversation in the dashboard. On Connect, it appears after First message received; otherwise find it in Inbox with the same app selected.
Reply with a recognizable message, such as
Hello back from the dashboard, and confirm it appears in the app's chat.Dismiss and reopen chat to check the entry point.
Sent confirms Reception accepted the message. Seeing your dashboard reply in the app confirms the return path. Building the app or opening an empty chat alone does not verify the connection.
If you are in onboarding, choose Continue to reach Integrations, then continue to Subscribe, the last step before the inbox. Push, Slack, Telegram, and reviews are also available in app settings.
If verification fails
| Symptom | What to check |
|---|---|
| Chat does not open | Configure before the button is used; check whether another sheet is already presenting. |
| The message is not sent | Check the copied configuration and internet connection. Follow any wait shown in chat, then use Retry when available. |
| The dashboard is still waiting | Check that you selected the app whose App ID is in your build. |
| A reply does not appear | Keep the app active with chat open and check its connection message. |
See Troubleshooting for more help. Something not working? Write to us in the Reception chat. We're happy to help. Briefly describe what happens and any error message you see.
Next steps
Users & accounts: show customer information and connect sign-in, sign-out, and account deletion.
Push notifications: let customers receive replies while away from the app; verify delivery on an iPhone or Android device.
Appearance and Language: match your existing theme and language settings.
Paywalls: open your app's existing purchase screen from a support card.
Dashboard: work with conversations, your team, and optional integrations.
API reference: look up Swift and Kotlin SDK calls and options.