### React Native SDK Installation Source: https://www.setgreet.com/docs/sdk/platforms Install the Setgreet React Native SDK using npm or yarn. ```bash npm install @setgreet/react-native-sdk ``` ```bash yarn add @setgreet/react-native-sdk ``` -------------------------------- ### Flutter pub.dev Installation Source: https://www.setgreet.com/docs/sdk/platforms Add the dependency to pubspec.yaml and fetch the package. ```yaml dependencies: setgreet: ^LATEST_VERSION ``` ```bash flutter pub get ``` -------------------------------- ### Verify Setgreet MCP installation with get_current_user Source: https://www.setgreet.com/docs/mcp Ask the agent to call the setgreet get_current_user tool to verify the install. Returns user, org, role, granted scopes, and token expiry. ```text Call the setgreet get_current_user tool. ``` -------------------------------- ### iOS Swift Package Manager Installation Source: https://www.setgreet.com/docs/sdk/platforms Add the Setgreet iOS SDK via Xcode or by updating your Package.swift file. ```text https://github.com/setgreet/setgreet-ios-sdk.git ``` ```swift dependencies: [ .package(url: "https://github.com/setgreet/setgreet-ios-sdk.git", .upToNextMajor(from: "LATEST_VERSION")) ] ``` -------------------------------- ### Initialize iOS SDK Source: https://www.setgreet.com/docs/sdk/platforms Initialize the SDK in your AppDelegate or App init using your App Key. ```swift // iOS - in AppDelegate or App init Setgreet.shared.initialize(appKey: "your_app_key", config: SetgreetConfig(debugMode: false)) ``` -------------------------------- ### Initialize Android SDK Source: https://www.setgreet.com/docs/sdk/platforms Initialize the SDK in your Application.onCreate() method. ```kotlin // Android - in Application.onCreate() Setgreet.initialize(context, "your_app_key", SetgreetConfig(debugMode = false)) ``` -------------------------------- ### Get anonymous ID on Flutter Source: https://www.setgreet.com/docs/sdk/user-identification Retrieves the auto-generated anonymous ID for the device on Flutter. ```dart // Flutter final anonId = await Setgreet.anonymousId; ``` -------------------------------- ### start_experiment Source: https://www.setgreet.com/docs/mcp/tools Transitions an experiment from DRAFT or PAUSED to RUNNING. Requires experiments:write scope. ```APIDOC ## start_experiment ### Description Transitions an experiment from DRAFT or PAUSED to RUNNING. Requires `experiments:write` scope. ### Method MCP Tool ### Endpoint `start_experiment` ### Parameters #### Path Parameters - **experiment_id** (string) - Required - The ID of the experiment to start. ### Response #### Success Response Returns the updated experiment status. #### Response Example (No explicit response example provided in source.) ``` -------------------------------- ### Get anonymous ID on Android Source: https://www.setgreet.com/docs/sdk/user-identification Retrieves the auto-generated anonymous ID for the device on Android. ```kotlin // Android val anonId = Setgreet.anonymousId ``` -------------------------------- ### Initialize Flutter SDK Source: https://www.setgreet.com/docs/sdk/platforms Initialize the SDK in your main.dart file. ```dart // Flutter - in main.dart import 'package:setgreet/setgreet.dart'; await Setgreet.initialize('your_app_key'); ``` -------------------------------- ### Get anonymous ID on iOS Source: https://www.setgreet.com/docs/sdk/user-identification Retrieves the auto-generated anonymous ID for the device on iOS. ```swift // iOS let anonId = Setgreet.shared.anonymousId ``` -------------------------------- ### Check Intro Eligibility (iOS only) Source: https://www.setgreet.com/docs/sdk/purchases Checks trial or introductory price eligibility for packages. Only runs on iOS because Google Play only provides offers the user can take. ```TypeScript async function introEligibility( packages: PurchasesPackage[] ): Promise> { if (Platform.OS !== 'ios' || packages.length === 0) { return {}; } try { return await Purchases.checkTrialOrIntroductoryPriceEligibility( packages.map((aPackage) => aPackage.product.identifier) ); } catch { return {}; } } ``` -------------------------------- ### Get anonymous ID on React Native Source: https://www.setgreet.com/docs/sdk/user-identification Retrieves the auto-generated anonymous ID for the device on React Native. ```javascript // React Native import { getAnonymousId } from '@setgreet/react-native-sdk'; const anonId = getAnonymousId(); ``` -------------------------------- ### Android: Setgreet.setFlowCallbacks Source: https://www.setgreet.com/docs/sdk/purchases Kotlin example for Android. setFlowCallbacks replaces any callbacks set before it, so add all callbacks to the same builder. ```Kotlin Setgreet.setFlowCallbacks { onPurchaseCompleted { event -> // event.productRef, event.accessRefs } onPurchaseCancelled { } onPurchaseFailed { event -> // event.error.code } onPurchasePending { } onRestoreCompleted { event -> // event.status, event.accessRefs } onRestoreFailed { } } ``` -------------------------------- ### list_subscription_plans Source: https://www.setgreet.com/docs/mcp/tools Lists all plans available on the platform (Free / Launch / Growth / Scale) with limits, prices, and features. Requires billing:read scope. ```APIDOC ## list_subscription_plans ### Description Lists all plans available on the platform (Free / Launch / Growth / Scale) with limits, prices, and features. ### Required Scope billing:read ### Parameters None ### Response - List of plans with limits, prices, and features ``` -------------------------------- ### iOS: Setgreet.shared.setFlowCallbacks Source: https://www.setgreet.com/docs/sdk/purchases Swift example for iOS. setFlowCallbacks replaces any callbacks set before it, so add all callbacks to the same builder. ```Swift Setgreet.shared.setFlowCallbacks { callbacks in callbacks .onPurchaseCompleted { event in // event.productRef, event.accessRefs } .onPurchaseCancelled { _ in } .onPurchaseFailed { event in // event.error.code } .onPurchasePending { _ in } .onRestoreCompleted { event in // event.status, event.accessRefs } .onRestoreFailed { _ in } } ``` -------------------------------- ### Check Intro Eligibility with _introEligibility Source: https://www.setgreet.com/docs/sdk/purchases Checks trial or introductory price eligibility for App Store products. Google Play is skipped as it does not require this call. ```dart /// App Store only: whether this user can take each product's introductory /// offer. Google Play needs no call (see [_playIntroOffer]), and RevenueCat /// answers "unknown" there anyway. Future> _introEligibility( List packages) async { if (_onGooglePlay) return const {}; try { return await Purchases.checkTrialOrIntroductoryPriceEligibility( [for (final package in packages) package.storeProduct.identifier], ); } catch (_) { // Best effort: unknown eligibility, so the SDK shows no trial text. return const {}; } } ``` -------------------------------- ### Purchase product implementation Source: https://www.setgreet.com/docs/sdk/purchases Handles the purchase flow for a specific product reference within a given source, including error normalization and status tracking. ```swift let packages = Dictionary( offering.availablePackages.map { ($0.identifier, $0) }, uniquingKeysWith: { first, _ in first } ) withLock { packagesBySource[Self.key(for: source)] = packages offeringsBySource[Self.key(for: source)] = offering } return offering } // MARK: - Purchase func purchase(productRef: String, source: SetgreetPurchaseSource) async -> SetgreetPurchaseResult { guard Purchases.isConfigured else { return SetgreetPurchaseResult( status: .failed, productRef: productRef, error: SetgreetPurchaseError(code: .providerNotInitialized) ) } let package: Package switch await resolvePackage(ref: productRef, in: source) { case .success(let found): package = found case .failure(let error): return SetgreetPurchaseResult(status: .failed, productRef: productRef, error: error) } do { let result = try await Purchases.shared.purchase(package: package) if result.userCancelled { return SetgreetPurchaseResult(status: .cancelled, productRef: productRef) } return SetgreetPurchaseResult( status: .purchased, productRef: productRef, accessRefs: Self.accessRefs(result.customerInfo) ) } catch { let normalized = Self.normalizedError(error, fallback: .purchaseFailed) switch normalized.code { case .purchaseCancelled: return SetgreetPurchaseResult(status: .cancelled, productRef: productRef, error: normalized) case .purchasePending: return SetgreetPurchaseResult(status: .pending, productRef: productRef, error: normalized) default: return SetgreetPurchaseResult(status: .failed, productRef: productRef, error: normalized) } } } ``` -------------------------------- ### Get Active Access References Source: https://www.setgreet.com/docs/sdk/purchases Returns the user's active entitlements as reported by RevenueCat, or null if the customer info cannot be retrieved. ```TypeScript async function activeAccessRefs(): Promise { try { return accessRefs(await Purchases.getCustomerInfo()); } catch { return null; } } ``` -------------------------------- ### get_screen Source: https://www.setgreet.com/docs/mcp/tools Fetches one DRAFT screen including components, background, and presentation style. ```APIDOC ## get_screen ### Description Fetches one DRAFT screen including components, background, and presentation style. ### Required Scope screens:read ### Parameters - **screen_id** (string) - Required - The id of the screen to fetch ### Response - **components** (array) - List of components - **background** (object) - Background configuration - **presentation_style** (object) - Presentation style ``` -------------------------------- ### update_organization Source: https://www.setgreet.com/docs/mcp/tools Updates organization name, size, or transfers ownership. Owner-only on the backend; non-owners get a forbidden error. No MCP scope required. ```APIDOC ## update_organization ### Description Updates organization name, size, or transfers ownership. Owner-only on the backend; non-owners get a forbidden error. ### Required Scope None (owner role required) ### Parameters - name (optional) - New organization name - size (optional) - New organization size - transfer_ownership (optional) - Transfer ownership to another user ### Response - Success or forbidden error for non-owners ``` -------------------------------- ### List Component Structure Source: https://www.setgreet.com/docs/components/layout Example structure of a List component containing a Card with Text and Image elements, using data binding syntax. ```text List Items: {{data.workout_plans.results}} Card Text {{item.name}} Text {{item.price}} Image {{item.image_url}} ``` -------------------------------- ### Initialize React Native SDK Source: https://www.setgreet.com/docs/sdk/platforms Initialize the SDK in your App.tsx or index.js file. ```typescript // React Native - in App.tsx or index.js import { initialize } from '@setgreet/react-native-sdk'; initialize('your_app_key'); ``` -------------------------------- ### setFlowCallbacks Source: https://www.setgreet.com/docs/sdk/displaying-flows Registers callbacks to listen for flow lifecycle events, allowing the app to respond to flow events such as start, completion, dismissal, and custom actions. ```APIDOC ## setFlowCallbacks ### Description Registers callbacks to listen for flow lifecycle events. This lets your app respond to what happens during a flow, such as navigating to a screen after the flow closes or logging a custom event. ### Usage Examples #### iOS ```swift Setgreet.shared.setFlowCallbacks { callbacks in callbacks .onFlowStarted { event in print("Flow started: \(event.flowId)") } .onFlowCompleted { event in print("Flow completed: \(event.flowId)") } .onFlowDismissed { event in print("Flow dismissed: \(event.flowId), reason: \(event.reason)") } .onActionTriggered { event in print("Action \(event.actionType) on flow \(event.flowId)") } .onCustomAction { event in print("Custom action on flow \(event.flowId): \(event.data ?? [:])") } } ``` #### Android ```kotlin Setgreet.setFlowCallbacks { onFlowStarted { event -> println("Flow started: ${event.flowId}") } onFlowCompleted { event -> println("Flow completed: ${event.flowId}") } onFlowDismissed { event -> println("Flow dismissed: ${event.flowId}, reason: ${event.reason}") } onActionTriggered { event -> println("Action ${event.actionType} on flow ${event.flowId}") } onCustomAction { event -> println("Custom action on flow ${event.flowId}: ${event.data}") } } ``` ### Available Lifecycle Callbacks - **onFlowStarted** - The flow began and the first screen appeared. - **onFlowCompleted** - The user reached the flow's final screen. - **onFlowDismissed** - The flow closed without being completed. - **onScreenChanged** - The user navigated to another screen within the flow. - **onActionTriggered** - A button action was triggered, just before it runs: next, URL, share, a permission request, a purchase and the rest. `actionType` names it. - **onPermissionRequested** - A permission request action fired (notifications, location, camera, tracking, microphone, photo library). - **onTrackEvent** - An in-flow `Track Event` action fired. - **onCustomAction** - A custom action defined in the dashboard fired. - **onError** - A flow the SDK set out to show could not be shown: the request failed, the response could not be read, or the flow could not be presented. ### Notes - The outcome of a paywall's purchase and restore buttons has its own callbacks, described in Purchases and paywalls. ``` -------------------------------- ### Fetch Offering with _loadOffering Source: https://www.setgreet.com/docs/sdk/purchases Internal method to resolve a purchase source to an offering, ensuring the provider is initialized and handling potential platform errors. ```dart /// Fetches the offering [source] resolves to and keeps its packages under /// that source, for [purchase]. Future _loadOffering(SetgreetPurchaseSource source) async { if (!await Purchases.isConfigured) { throw const SetgreetPurchaseError( code: SetgreetPurchaseErrorCode.providerNotInitialized, message: 'Purchases.configure(...) has not been called', ); } final Offering? offering; try { offering = await _offering(source); } on PlatformException catch (error) { throw _normalizedError(error, SetgreetPurchaseErrorCode.networkError); } if (offering == null) { throw SetgreetPurchaseError( code: SetgreetPurchaseErrorCode.productNotFound, message: 'No offering for ${source.sourceType} ${source.sourceId ?? ''}', ); } // The first package of an identifier wins, as RevenueCat lists them. final packages = {}; for (final package in offering.availablePackages) { packages.putIfAbsent(package.identifier, () => package); } _packagesBySource[source] = packages; _offeringsBySource[source] = offering; return offering; } ``` -------------------------------- ### Get Access State from RevenueCat Source: https://www.setgreet.com/docs/sdk/purchases Returns the current access state based on active entitlements. Returns null if RevenueCat is not configured or customer info cannot be fetched. ```Dart // Access @override Future accessState() async { if (!await Purchases.isConfigured) return null; final CustomerInfo info; try { info = await Purchases.getCustomerInfo(); } on PlatformException { return null; } final refs = _accessRefs(info); return SetgreetPurchaseAccessState( active: refs.isNotEmpty, accessRefs: refs); } ```