API reference
Swift API reference
The complete public ReceptionKit API for configuration, identity, chat presentation, notifications, observable state, appearance, events, and deletion errors. Signatures and behavior on this page follow the current Swift sources.
Overview
Use this reference to look up an individual method, property, or type. The iOS SDK guides walk through integrating those APIs into your app, with examples for presentation, unread badges, account changes, and push notifications.
Import ReceptionKit in your app. Import SwiftUI for views and appearance values, and Foundation when using URL or Data without SwiftUI. ReceptionKit requires iOS 17 or later. See Get started to add the package.
Configuration, instance members, and ReceptionChatView require the main actor. Static logging settings and version can be accessed from any thread. The reference shows inherited @MainActor isolation explicitly. From asynchronous code outside the main actor, use an actor hop; do not move a notification's untyped payload across actors without following the push integration guidance.
Only deleteData() is asynchronous and throwing. The other facade methods return synchronously; completion does not confirm a server update. Device registration begins on the first valid send attempt. Configuration and staging identity do not register an unused device. The configured SDK or a visible chat may independently fetch public project appearance before the first message.
| Area | Public members |
|---|---|
| Configure | configure, isConfigured |
| Chat behavior | Connection and retry |
| Logging | logLevel, logHandler, version |
| Identity | identify, identify(token:), setMetadata |
| Present | openChat, closeChat, ReceptionChatView |
| Push | setPushToken, handlePushNotification, Reception.PushEnvironment |
| Paywall cards | paywalls, onPaywall, paywallAvailability, availablePaywalls, refreshPaywalls, ReceptionPaywall |
| Lifecycle | logout, deleteData |
| State and settings | shared, unreadCount, isChatOpen, updatesAppBadge, appearance, usesRemoteAppearance, languageOverride, onEvent |
| Value types | Reception.Appearance, Reception.CloseIcon, ReceptionEvent, ReceptionError |
Reception
Declaration from Reception.swift:
@MainActor @Observable
public final class ReceptionUse Reception.configure once during startup, then access chat and instance settings through Reception.shared. The facade has no public initializer. Logging settings and the SDK version are static members of Reception.
Configuration
configure
@MainActor
public static func configure(appId: String)Call once during app startup, before supplying identity or creating support views. appId is your public Reception App ID, starting with app_, from Settings → Apps → your app → Setup in the dashboard. It is safe to include in your app. Reception hosts the service, so your app needs no other configuration.
import ReceptionKit
@MainActor
func configureSupport() {
Reception.configure(appId: "app_YOUR_APP_ID")
}Configuration does not register an unused device or load its chat. Support registration starts with the first valid send attempt. Published appearance can load before that. Repeating the same App ID is a no-op. A different App ID switches the local support session, clears the displayed unread count, and dismisses the SDK sheet; it does not delete stored server data.
A malformed App ID is ignored with a developer error log. An identity secret is not an App ID and must never be included in your app. Use isConfigured to check whether configuration was accepted; it does not test connectivity.
isConfigured
@MainActor
public static var isConfigured: Bool { get }It is true once a valid configure(appId:) call has been accepted in this process. It does not mean a device has registered or that chat is connected. Use it before calling methods that require configuration, such as identify or openChat.
Identity and lifecycle
identify
Facade declaration:
@MainActor
public func identify(userId: String?, name: String? = nil, email: String? = nil)userId is required; name and email are optional and default to nil. userId is your app's stable account identifier, name is a display name, and email is the user's email address. Pass nil for unavailable values. Values are not trimmed. The limits are 255 characters for user ID, 200 for name, and 254 for email. Some emoji count as more than one character. ReceptionKit leaves out a longer value and logs an error.
Replaces the three locally staged identity fields, leaving staged metadata and push registration intact. It does nothing before configuration and does not initiate a request. Values travel with registration or the next device update, such as a chat load, send, or foreground synchronization after support has started.
A nil value is omitted from the request; it does not clear an existing server field. Identification labels this device and does not authenticate your host account, merge devices, or restore another device's conversation. Call logout() before switching accounts. On a chat verified through identify(token:), these values no longer change the identity; a different user ID only logs an error. See Identity and Login and logout.
Place this in your main-actor session-restoration or successful-login handler, after configuration:
Reception.shared.identify(userId: "user_123", name: "Alex", email: "[email protected]")identify(token:)
Facade declaration:
@MainActor
public func identify(token: String)Stages an identity token that your server signed for identity verification. ReceptionKit keeps it in memory only and sends it with the next registration or device update, such as a chat load, send, or foreground synchronization after support has started. Passing the same token as last time does nothing. Call it after sign-in and on every launch while a user is signed in. It does nothing before configuration. Switching users also requests remote sign-out of the old session.
The call reads the token's user_id right away, without verifying it. If that user differs from the verified or identified user of the current chat, ReceptionKit immediately ends the old session and resets local state as logout() does; only the new token and the push token carry over. The next send starts a new chat for the token's user.
An ids_ secret, an overlong token, or a token whose user_id the SDK can't read is ignored locally without an event. Other invalid tokens may reach Reception and emit identityRejected.
If Reception rejects the token as invalid, expired, or unconfigured, ReceptionKit drops it, logs an error, and emits identityRejected. Existing verification is unchanged; unverified chats remain subject to the app’s verified-only setting. A rejected registration leaves the send ready to retry. If the current registration belongs to another user, ReceptionKit resets the old session and keeps the new token for the next send.
logout(), deleteData(), and configuring another App ID forget the token. It never replaces logout() at sign-out.
Place this in your main-actor sign-in and session-restoration handlers, after configuration, with a token from your server:
Reception.shared.identify(token: token)setMetadata
Facade declaration:
@MainActor
public func setMetadata(_ metadata: [String: String])The unlabeled argument is required. Replaces the entire staged dictionary; it does not merge keys. Pass [:] to replace metadata with an empty dictionary on the next device update. Identity and push values remain staged separately.
Does nothing before configuration and makes no immediate request. Keys and values must be strings; convert numbers and booleans to your intended display strings. Up to 20 entries are allowed, with keys of 1–64 characters and values up to 512 characters. Entries outside those length limits are omitted. Supplying more than 20 entries replaces the dictionary with an empty one, clearing saved metadata on the next successful synchronization. There is no completion callback or flush method.
Place this in your main-actor account or subscription update handler. Supply the full set of fields you want to retain:
Reception.shared.setMetadata(["plan": "Pro", "provider": "RevenueCat"])logout
Facade declaration:
@MainActor
public func logout()Immediately clears this device's local support session, identity, metadata, push registration, chat history, draft, pending sends, and unread state, and dismisses the SDK sheet. Server history remains.
ReceptionKit also asks the service to end the old session. Returning from this synchronous method does not confirm that request completed; notifications already in flight can still arrive. See Login and logout.
The next send starts a new session. Reapply the current identity, metadata, and APNs token. Configuration, appearance, language, badge preference, and event handlers remain. Logout emits no event.
Place this in your main-actor sign-out handler, before identifying a different user:
Reception.shared.logout()deleteData
Facade declaration:
@MainActor
public func deleteData() async throwsAsks Reception to delete the current device's support data, including conversations and images. It does not delete your app's user account or support data on other devices.
Completion resets local state, dismisses the SDK sheet, and emits .dataDeleted. With no session, or when Reception no longer recognizes the session or app, completion can be local only: it is not a receipt proving that historical server data was erased. Before configuration, the method does nothing.
Failures throw ReceptionError and keep the current session available for retry. A failed response does not establish whether deletion finished on the server. If the active session changes during deletion, its replacement is preserved. Await deletion before continuing your account transition.
Place this helper in your host account-deletion flow. Its caller must catch failures, present retry, and advance the account flow only after successful return:
import ReceptionKit
@MainActor
func deleteSupportDataBeforeContinuing() async throws {
try await Reception.shared.deleteData()
}See Delete data for the complete host-owned flow and deletion limits.
Presentation
openChat
Facade declaration:
@MainActor
public func openChat()No arguments, return value, or thrown errors. Presents the SDK chat sheet over the current screen in SwiftUI and UIKit apps. If no screen is ready yet, such as during a cold start, ReceptionKit opens it after the app becomes active. A call while chat is already visible does nothing.
Configure first. openChat() does not confirm visibility, emit .chatOpened by itself, or control a host-owned navigation path. Use Reception.shared.isChatOpen for visibility. Host-owned sheets and navigation use SwiftUI dismissal or host state.
Place this view below your configured app root. The host supplies the entry-point label and layout:
import SwiftUI
import ReceptionKit
@MainActor
struct AppRoot: View {
var body: some View {
Button("Support") { Reception.shared.openChat() }
}
}closeChat
Facade declaration:
@MainActor
public func closeChat()Dismisses the chat sheet presented by openChat() or a notification tap. It does nothing when the chat is not presented by the SDK; a ReceptionChatView placed by the host is dismissed by the host.
ReceptionChatView
View declaration:
@MainActor
public struct ReceptionChatView: ViewUse directly for a host-owned sheet or navigation destination. When presented, it supplies a navigation stack, native drag indicator, and the optional appearance-controlled close button. Embedded content uses the host's navigation context. The view applies SDK localization, layout direction, and appearance; visible active chat manages message loading, read state, and live updates.
Your host controls direct presentation and dismissal. Do not also call Reception.shared.openChat() for the same action: that method and forwarded push taps always use the SDK sheet. Unread monitoring already starts with configuration.
ReceptionChatView.init
Initializer declaration:
@MainActor
public init()No arguments and no thrown errors. Configure Reception before creating the view. Constructing it does not mean it is visible or that a device has registered.
Place this navigation destination in your host's SwiftUI screen after configuration:
NavigationStack {
NavigationLink("Support") {
ReceptionChatView()
}
}ReceptionChatView.body
Property declaration:
@MainActor
public var body: some View { get }Read-only SwiftUI content. SwiftUI evaluates this property; compose ReceptionChatView() rather than invoking body directly.
Push
setPushToken
Facade declaration:
@MainActor
public func setPushToken(
_ token: Data,
environment: Reception.PushEnvironment = .automatic
)token is the required raw APNs token received by your app delegate. Do not pass a UTF-8 encoding of its hexadecimal description. environment defaults to .automatic; see Reception.PushEnvironment for resolution and explicit overrides.
After configuration, stages a lowercase hexadecimal token and its resolved environment. Empty tokens, unresolved environments, and calls without a configured session are ignored. There is no fixed APNs token byte count enforced by the method.
If a stored session exists, schedules a device update and unread refresh, subject to support having started. An unused device is not registered just to store push details. This method does not request notification permission, register with APNs, or confirm delivery; the host owns those steps. Call again when APNs supplies a token and after resetting the local session.
Place this statement in the host app's main-actor APNs registration callback, where deviceToken is the callback's Data argument:
Reception.shared.setPushToken(deviceToken)handlePushNotification
Facade declaration:
@MainActor @discardableResult
public func handlePushNotification(
userInfo: [AnyHashable: Any],
openChat: Bool = true
) -> BooluserInfo is required. Returns true only when userInfo["reception"] casts to [String: Any] and contains a nonempty String conversationId. Other payloads return false without requesting presentation or refreshing unread state.
For a recognized payload, presents the SDK sheet if openChat is true, including after a cold start, and schedules an unread refresh if support has started. Use the default for notification taps and false for foreground receipt. The result means the payload shape was recognized, not that the chat appeared, a request succeeded, or the identifier belongs to the current device. The ID is not used to navigate to a historical conversation; the SDK opens its current chat. The method does not require an aps dictionary and does not apply its badge value directly.
The host still controls notification banners, sound, completion handlers, and routing for other notifications. See Push notifications for delegate examples and actor-safe forwarding.
Reception.PushEnvironment
Type declaration:
public enum PushEnvironment: SendableA value type with three cases and no associated values. It has no public raw-value conversion or environment-resolution method, and is not declared @MainActor.
Reception.PushEnvironment cases
Case declarations:
case automatic, sandbox, production| Case | Behavior |
|---|---|
.automatic | Default token setting. On a physical device, reads aps-environment from the embedded provisioning profile: development means sandbox, production means production. No embedded profile means production. An unreadable, malformed, or unrecognized profile resolves to no update. On the simulator, resolves to no update. |
.sandbox | Explicitly sends SANDBOX for development provisioning. |
.production | Explicitly sends PRODUCTION for distribution provisioning. |
Explicit overrides bypass automatic detection. They do not create a valid token or prove APNs delivery; verify push with a real device and matching provisioning.
Observable state and settings
shared
Property declaration:
@MainActor
public static let shared: ReceptionThe single shared facade, created by the SDK. Read instance state through this property; it cannot be replaced. Static settings and methods operate on the same instance.
unreadCount
Property declaration:
@MainActor
public private(set) var unreadCount: Int = 0Read as Reception.shared.unreadCount. Observable in SwiftUI and not writable by the host. Starts at zero and is clamped to a nonnegative value. Represents the current device's latest-conversation unread count from SDK synchronization, not a cross-device total. Before synchronization, zero is not proof that the server has no unread messages.
After marking displayed messages read, the count reflects any replies still unread; a new reply can keep it above zero. Configuration and local resets set it to zero. ReceptionKit updates it automatically as support activity and app state change. See Unread messages for a badge example.
isChatOpen
Property declaration:
@MainActor
public var isChatOpen: Bool { get }Read as Reception.shared.isChatOpen. Initially false; becomes true when chat content appears and false when it disappears. SwiftUI observes its underlying state. It reflects visibility, including direct presentation, and is not a connection or app-foreground indicator. A pending openChat() presentation does not make it true.
updatesAppBadge
Property declaration:
@MainActor
public var updatesAppBadge: Bool = trueWhen enabled, SDK unread synchronization sets the app icon badge, even if the count did not change. At zero it also removes delivered Notification Center entries whose userInfo contains reception; other entries remain. Badge-setting errors are ignored.
Set false during app initialization when the host owns the icon badge and notification cleanup. It disables both SDK actions without changing unreadCount. Registration includes this preference; changes are synchronized asynchronously for an active support session, with retries after failures and on foreground. Once saved, subsequent support pushes omit aps.badge entirely while retaining their alert and configured sound. Offline, the server uses the last successfully saved preference; already prepared or delivered notifications are not changed. Assigning the flag does not clear or recalculate an existing badge. Set it on each app launch; its default is true. Reception does not combine counts from other host features. See Unread messages.
appearance
Property declaration:
@MainActor
public var appearance: Appearance { get set }Defaults to Reception.Appearance(). Read, replace, or mutate local styling. The getter returns local values, without the published remote overrides used by the displayed chat. The 14-property index links to each canonical option, its default, and behavior.
Each appearance option accepts values from your Swift variables or theme objects when their types match. Reassign values when your app changes its theme; these assignments do not create bindings. See Use your app’s theme and variables for an example, adaptive colors, and dashboard precedence.
usesRemoteAppearance
Property declaration:
@MainActor
public var usesRemoteAppearance: Bool { get set }Defaults to true. Enables published remote appearance overrides on top of local values. Set false to use local appearance only. Published changes refresh while the app is active and become visible on a later chat opening. If an appearance update can't be downloaded, the chat keeps its previous styling. See Remote appearance and precedence.
languageOverride
Property declaration:
@MainActor
public var languageOverride: String? { get set }Defaults to nil, following the iOS-selected localization of the host app. Set a BCP 47 tag for a custom in-app language picker; assign nil to restore automatic selection. The getter returns the supplied override, not the resolved SDK language. Assigning the same value has no effect.
The SDK canonicalizes language tags, matches its 48 supported localizations, and falls back to English for invalid or unsupported selections. Built-in labels, formatting, direction, default appearance text, and available remote translations follow the selection. Host-supplied strings and existing messages remain unchanged. An unused device is not registered by changing language; started sessions synchronize the selection through device updates with retry. See Language for all supported codes and matching rules.
Events
onEvent
Property declaration:
@MainActor
public var onEvent: ((ReceptionEvent) -> Void)?Defaults to nil. Assign one synchronous handler; another assignment replaces it. Set nil to remove it. SDK call sites invoke it on the main actor. Keep the handler short and schedule lengthy work separately. There is no event history, subscription token, or replay. Local resets do not remove this handler.
Place this in main-actor startup code to observe successful SDK sends:
Reception.shared.onEvent = { event in
switch event {
case .messageSent:
print("Support message confirmed")
default:
break
}
}ReceptionEvent
Type declaration:
public enum ReceptionEvent: HashableSeven cases. Only identityRejected carries a value: the ReceptionError of a rejected identity token. The type is Equatable and Hashable, so comparisons such as event == .messageSent work. Events carry no user identifiers or message bodies. See Events for analytics integration.
ReceptionEvent cases
Case declarations:
case chatOpened, messageSent, imageSent, reviewOpened, paywallOpened
case dataDeleted
case identityRejected(ReceptionError)| Case | Exact trigger |
|---|---|
.chatOpened | Chat content's onAppear, including host-owned presentation. May fire again on a later appearance. Calling openChat() alone does not emit it. |
.messageSent | A successful send response for the current session, including image messages and successful retries. Does not fire when merely queuing a draft or imply an agent read it. |
.imageSent | Immediately after .messageSent if the confirmed draft contains images. Once per send, not once per image. |
.reviewOpened | When the review-card action is invoked, immediately before opening its URL. Does not confirm URL-opening success or a submitted review. |
.paywallOpened | When an available paywall-card action is invoked. Reports the tap, not successful presentation or purchase. |
.dataDeleted | Completion of deleteData(), including local-only completion, unknown or ended sessions, and an unavailable app. Does not certify server-side erasure. Not emitted by failed deletion or logout(). Still emitted if a replacement session was preserved during deletion. |
.identityRejected(_:) | Reception rejected the staged identity token with identity_token_invalid, identity_token_expired, or identity_not_configured. ReceptionKit has dropped the token; existing verification is unchanged, and unverified chats remain subject to the verified-only setting. Fetch a new token for identity_token_expired; the other codes need a fix on your server or in the dashboard. |
Appearance
Reception.Appearance
Type declaration:
public struct AppearanceA value type with 14 public writable properties. Only title, welcomeTitle, and welcomeText are individually declared @MainActor; accessing any option through Reception.shared.appearance requires the main actor. Detailed property signatures, defaults, examples, and constraints live on Appearance.
Reception.Appearance.init
Initializer declaration:
public init()No arguments and no thrown errors. Creates the default local appearance. There is no public memberwise initializer accepting appearance fields; create a value and mutate its properties. Assigning a fresh value to Reception.shared.appearance restores local defaults but does not remove active remote overrides.
Reception.Appearance property index
See what each option changes, then follow its link for defaults, allowed values, and a Swift example. All 14 properties are readable and writable.
| Property | Type | What changes |
|---|---|---|
accentColor | Color | Outgoing bubble fills and accented controls |
onAccentColor | Color? | Text and symbols on accent surfaces |
title | String (@MainActor) | Navigation title at the top of chat |
welcomeTitle | String (@MainActor) | Heading shown in an empty chat |
welcomeText | String (@MainActor) | Supporting text below the welcome heading |
showsCloseButton | Bool | Visibility of the presented chat’s close button |
chatBackground | Color? | Background surface behind the conversation |
incomingBackground | Color? | Incoming bubble, review card, and paywall card fills |
incomingForeground | Color? | Incoming message text and review/paywall card body text |
preferredColorScheme | ColorScheme? | Follow the app, or force light or dark mode |
closeIcon | Reception.CloseIcon | Close button symbol: cross, chevron, or arrow |
fontDesign | Font.Design? | System font design, such as rounded or serif |
fontFamily | String? | Custom font bundled by your app |
fadesOlderMessages | Bool | Lighter fills for older outgoing text bubbles |
Reception.CloseIcon
Type declaration:
public enum CloseIcon: String, SendableSelects the symbol used when the chat's close button is shown. No actor isolation is declared on the type. Changing the icon does not make the button visible; configure showsCloseButton separately.
Reception.CloseIcon cases
Case declarations and their exact SF Symbol raw values:
case xmark
case chevronDown = "chevron.down"
case arrowDown = "arrow.down"The raw value of .xmark is "xmark". Reception.Appearance.closeIcon defaults to .xmark.
Reception.CloseIcon.rawValue
Synthesized property declaration:
public var rawValue: String { get }Read-only raw string for the selected case. The raw values are exactly "xmark", "chevron.down", and "arrow.down".
Reception.CloseIcon.init(rawValue:)
Synthesized initializer declaration:
public init?(rawValue: String)The required, case-sensitive string must match a raw value exactly. Unknown strings return nil; the initializer does not throw or choose a fallback icon.
Errors
ReceptionError
Type declaration:
public struct ReceptionError: Error, Hashable, SendableThrown by Reception.shared.deleteData() when completion cannot be established, and carried by the identityRejected event. It has two read-only public properties and no public initializer. It is not an enum; error codes are an open set of strings. Other public facade methods do not throw. Chat request failures are handled by the built-in chat UI.
ReceptionError.code
Property declaration:
public let code: StringThe server error code, when available, or an SDK-generated failure code. Match codes you need and retain a fallback for unfamiliar ones. No localized user-facing error message is exposed by this property.
ReceptionError.status
Property declaration:
public let status: IntHTTP status, or zero for transport, storage, or configuration failures without a valid HTTP response. A response-decoding error retains the HTTP status, including 200.
Deletion error codes
| Code | Status and meaning |
|---|---|
connection_failed | 0: transport failure or another unmapped deletion failure. |
cancelled | 0: a request failure while the task is cancelled. Cancellation does not prove the server stopped deletion. |
secure_storage_unavailable | 0: the Keychain could not be read, for example before the first unlock after a restart. The session stays; retry later. |
invalid_configuration | 0: the SDK could not use its service address to construct a request. Contact Reception if this occurs. |
invalid_url | 0: the endpoint URL could not be constructed. |
invalid_response | 0 for a non-HTTP response, or the received HTTP status for a response that cannot be decoded. |
http_error | The received non-200 HTTP status when no server error envelope could be decoded. |
delete_failed | Server 503: deletion could not be completed. Keep the session and retry; some data may already have been removed. |
| Other server codes | The server's code and status pass through, including internal_error with 500. |
Keep the current local session on failure and offer retry. Contact Reception for configuration errors; retry temporary transport or server failures when the service is available. Do not infer successful deletion from a failed request or clear the session in an error handler. See Delete data and Troubleshooting.
Connection and retry
ReceptionKit handles connection recovery and temporary sending pauses. A message is Sent only after Reception confirms it. If a message shows Not delivered, follow the notice in chat and use Retry when available. Previously submitted messages can resume when the connection recovers or chat is reopened; an unsent draft is not sent automatically.
Your app does not need its own retry loop. Closing chat or leaving the app does not guarantee completion of a pending send. See Chat features for visible states and Troubleshooting if a problem persists.
Logging
Use developer logs in Xcode to investigate an integration issue. Ordinary chat errors are shown in the chat interface; your users do not need to collect logs.
logLevel
nonisolated public static var logLevel: Reception.LogLevel { get set }Minimum level that is emitted. Defaults to .info. Set it before configure:
Reception.logLevel = .debugReception.LogLevel
| Case | Emits |
|---|---|
.off | No ordinary SDK logs; requested setup-check messages remain visible. |
.error | Errors that need attention. |
.info | Errors and significant SDK lifecycle events. Default. |
.debug | Additional diagnostics for development and troubleshooting. |
Levels are Comparable; .debug includes .info and .error.
logHandler
nonisolated public static var logHandler: (@Sendable (Reception.LogLevel, String) -> Void)? { get set }Defaults to nil. When set, ordinary SDK log lines go to the handler instead of the console. Requested setup-check messages still appear in Xcode and are not forwarded to this handler. Use it to forward SDK logs to your own logging system. The message has no [Reception] prefix; your handler owns the format. Both logLevel and logHandler may be read from any thread.
version
nonisolated public static var version: String { get }The SDK version, for example 0.1.0. Include it when asking for integration help; it is also shown in dashboard device details.
Log privacy
SDK logs omit message text, image URLs, identity and metadata values, and authentication secrets. They can contain diagnostic identifiers. Review logs before sharing them and apply your app's own logging policy to a custom handler.
Version and package
The library product and import name are ReceptionKit. The current manifest uses Swift tools version 6.0, Swift language mode 5, strict concurrency checking, and iOS 17 as the minimum platform. It has no external package dependencies. Use the setup instructions in Get started for the package URL and supported integration workflow.
Paywall cards
Connect chat cards to purchase screens your app already owns. Reception records card opens; purchases stay with your app and payment provider. Follow Paywall cards for a complete integration.
paywalls
@MainActor
public var paywalls: [ReceptionPaywall] { get set }Defaults to []. Assign your registered destinations during app setup, with stable IDs and titles your team recognizes. Titles appear only in the dashboard. Assignment replaces the list. IDs and titles are trimmed. IDs must contain 1–64 characters: ASCII letters, digits, underscores, dots, or hyphens. Titles must contain 1–60 characters. The SDK keeps the first 20 valid destinations with unique IDs and omits the rest.
Reception.shared.paywalls = [
ReceptionPaywall(id: "plans", title: "Plans")
]onPaywall
@MainActor
public var onPaywall: ((String) -> Void)?Defaults to nil. Receives the ID of an available card the customer tapped. Use the handler to open your existing purchase screen above chat. A card needs both an available destination and this handler; otherwise it appears unavailable. See Present your paywall for host and provider examples.
paywallAvailability
@MainActor
public var paywallAvailability: (@MainActor (String) async -> Bool)?Defaults to nil, which makes every registered destination available. Set a handler that returns whether the current user can see each destination, for example based on their subscription. Assigning a non-nil handler clears availablePaywalls while the new check runs. Assigning nil immediately makes all registered destinations available. Keep account and purchase decisions in your app.
availablePaywalls
@MainActor
public private(set) var availablePaywalls: [ReceptionPaywall]Read-only available destinations, in registered order. Initially empty. Without an availability handler, this follows paywalls; with one, it contains the destinations the handler approved. The list determines which cards agents can send and customers can open.
refreshPaywalls
@MainActor
public func refreshPaywalls(invalidate: Bool = false)Starts an availability refresh. With an availability handler, the default keeps current destinations available while it runs; pass true to clear them until the result is ready. Without a handler, all registered destinations remain available. The method returns synchronously; observe availablePaywalls for the result.
Call this from your main-actor subscription-change handler:
Reception.shared.refreshPaywalls(invalidate: true)ReceptionKit also refreshes during normal app and chat lifecycle changes. See Paywall cards for complete examples.
ReceptionPaywall
public struct ReceptionPaywall: Sendable, Hashable {
public let id: String
public let title: String
public init(id: String, title: String)
}A destination's stable identifier and the title agents see in the dashboard. Customers never see the title. Both initializer arguments are required. Register values through paywalls so the supported input limits apply.