### Install Referrer API Source: https://limelink.org/md/android-sdk Methods to retrieve app installation source information and structured LimeLink metadata. ```APIDOC ## GET /install-referrer ### Description Retrieves the raw install referrer string and structured LimeLink metadata from the Play Store. ### Method GET (SDK Wrapper) ### Parameters - **context** (Context) - Required - The application context. ### Response #### Success Response (200) - **referrerUrl** (String) - Raw referrer string. - **clickTimestamp** (Long) - Ad click time. - **installTimestamp** (Long) - App install start time. - **limeLinkDetail** (Object) - Structured details including `url`, `fullUrl`, and `queryParams`. ### Response Example { "referrerUrl": "utm_source=kakao&campaign=summer", "clickTimestamp": 1625000000, "installTimestamp": 1625000100, "limeLinkDetail": { "url": "https://abc.limelink.org/link/test", "queryParams": {"utm_source": "kakao", "campaign": "summer"} } } ``` -------------------------------- ### Universal Link Flow Examples Source: https://limelink.org/md/ios-sdk Examples of Universal Link URLs used by the LimeLink SDK. The subdomain method is recommended and includes optional query parameters. The direct access method uses a different API endpoint. ```plaintext https://{subdomain}.limelink.org/link/{linkSuffix} https://{subdomain}.limelink.org/link/{linkSuffix}?campaign=summer&source=email ``` ```plaintext https://limelink.org/api/v1/app/dynamic_link/{suffix} https://limelink.org/universal-link/app/dynamic_link/{suffix} ``` -------------------------------- ### Retrieve and Parse Install Referrer Information Source: https://limelink.org/md/android-sdk Retrieves installation source data and parses the LimeLink URL into structured components like query parameters and base URLs. ```kotlin LimeLinkSDK.getInstallReferrer(context) { referrerInfo -> val detail = referrerInfo?.limeLinkDetail if (detail != null) { Log.d("Detail", "url: ${detail.url}") Log.d("Detail", "queryParams: ${detail.queryParams}") } } ``` -------------------------------- ### Distinguishing Universal Link vs Deferred Deeplink Source: https://limelink.org/md/android-sdk Example code demonstrating how to differentiate between a Universal Link (app is running) and a Deferred Deep Link (app was just installed) within the `onDeeplinkReceived` callback. ```APIDOC ## DELETE /api/users/{userId} ### Description Deletes a user account from the system. Requires the user's ID. ### Method DELETE ### Endpoint /api/users/{userId} ### Parameters #### Path Parameters - **userId** (string) - Required - The unique identifier of the user to delete. #### Query Parameters - **none** ### Request Example ``` DELETE /api/users/usr_12345abcde ``` ### Response #### Success Response (204 No Content) - No response body is returned upon successful deletion. #### Response Example (No content) #### Error Response (404 Not Found) - **error** (string) - A message indicating that the user with the specified ID was not found. #### Error Response Example ```json { "error": "User with ID 'usr_12345abcde' not found." } ``` ``` -------------------------------- ### Query String Handling Example Source: https://limelink.org/md/ios-sdk Demonstrates how query parameters from an original URL are preserved and included in the API call for Universal Link resolution. This ensures all tracking and contextual information is passed to the backend. ```plaintext Original: https://abc.limelink.org/link/test?campaign=summer&source=email API call: GET /api/v1/app/dynamic_link/test?full_request_url=https://abc.limelink.org/link/test?campaign=summer&source=email ``` -------------------------------- ### Create Dynamic Link Request Example Source: https://limelink.org/md/api-integration This example demonstrates how to construct a JSON request body to create a dynamic link using the API. It includes root-level parameters and platform-specific options for iOS and Android, along with additional options for social previews and UTM tracking. ```JSON { "dynamic_link_suffix": "my_unique_link_suffix", "dynamic_link_url": "https://www.example.com/target", "dynamic_link_name": "My Link Name", "project_id": "your_project_id", "stats_flag": true, "apple_options": { "application_id": "com.example.ios", "request_uri": "/some/path/in/app", "not_installed_options": { "custom_url": "https://www.example.com/download" } }, "android_options": { "application_id": "com.example.android", "request_uri": "/some/path/in/app", "not_installed_options": { "custom_url": "https://www.example.com/download" } }, "additional_options": { "preview_title": "Check out this link!", "preview_description": "A great link with amazing content.", "preview_image_url": "https://www.example.com/image.jpg", "utm_source": "newsletter", "utm_medium": "email", "utm_campaign": "summer_sale" } } ``` -------------------------------- ### SDK Initialization in AppDelegate Source: https://limelink.org/md/ios-sdk Initializes the LimeLink SDK upon application launch by creating a `LimeLinkConfig` object with the API key and other settings, then calling `LimeLinkSDK.initialize()`. This setup is crucial for the SDK's functionality. ```swift import UIKit import LimelinkIOSSDK @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Initialize LimeLink SDK let config = LimeLinkConfig( apiKey: "YOUR_API_KEY", loggingEnabled: false, // Set to true for debug builds deferredDeeplinkEnabled: true ) LimeLinkSDK.initialize(config: config) return true } } ``` -------------------------------- ### Handling Deferred vs. Universal Links (Kotlin) Source: https://limelink.org/md/android-sdk This Kotlin code snippet demonstrates how to differentiate between a deferred deep link and a standard universal link within the `onDeeplinkReceived` callback. It shows how to access referrer information for deferred links, which is useful for tracking install sources. ```kotlin override fun onDeeplinkReceived(result: LimeLinkResult) { if (result.isDeferred) { // App launched for the first time after install — restored link from before installation val referrer = result.referrerInfo Log.d("Deferred", "referrer url: ${referrer?.limeLinkUrl}") Log.d("Deferred", "query params: ${referrer?.limeLinkDetail?.queryParams}") } else { // Universal Link clicked while app is running Log.d("UniversalLink", "Received universal link: ${result.resolvedUri}") } } ``` -------------------------------- ### CocoaPods Installation (Podfile) Source: https://limelink.org/md/ios-sdk Defines the LimeLink iOS SDK dependency within the Podfile for CocoaPods integration. This allows for easy management of the SDK as a project dependency. ```ruby platform :ios, '12.0' use_frameworks! target 'YourApp' do pod 'LimelinkIOSSDK' end ``` -------------------------------- ### Install Limelink SDKs Source: https://limelink.org/llms.txt Instructions for integrating the Limelink SDK into mobile projects using CocoaPods for iOS or Gradle for Android. These dependencies enable deep linking and analytics tracking within mobile applications. ```ruby pod 'LimelinkIOSSDK' ``` ```gradle maven { url 'https://jitpack.io' } implementation 'com.github.hellovelope:limelink-aos-sdk:0.1.0' ``` -------------------------------- ### Swift Package Manager Installation (Package.swift) Source: https://limelink.org/md/ios-sdk Specifies the LimeLink iOS SDK dependency in the Package.swift file for Swift Package Manager integration. This ensures the SDK is included as a dependency for your project. ```swift dependencies: [ .package(url: "https://github.com/hellovelope/limelink-ios-sdk.git", from: "0.2.0") ] ``` ```swift .target( name: "YourApp", dependencies: [ .product(name: "LimelinkIOSSDK", package: "limelink-ios-sdk") ] ) ``` -------------------------------- ### Handle Deferred Deep Link with Suffix Source: https://limelink.org/md/android-sdk Processes a deferred deep link manually when the suffix and full request URL are already available, such as from custom Install Referrer handling. ```kotlin LimeLinkSDK.handleDeferredDeepLink( suffix = "campaign-xyz", fullRequestUrl = "https://abc.limelink.org/link/campaign-xyz" ) { resolvedUri -> resolvedUri?.let { navigateTo(it) } } ``` -------------------------------- ### Manual Deferred Deep Link Handling (Swift) Source: https://limelink.org/md/ios-sdk Provides an example of how to manually trigger the handling of deferred deep links using the LimeLink SDK. This is used when automatic detection is disabled, allowing developers to call the handler at a specific point in the app's lifecycle. ```swift LimeLinkSDK.shared.handleDeferredDeepLink { result, error in if let result = result { // result.isDeferred == true // result.resolvedUri contains the deep link URI } if let error = error { // No match found or network error } } ``` -------------------------------- ### GET /api/v1/app/dynamic_link/{suffix} Source: https://limelink.org/md/android-sdk This endpoint is used by the SDK to resolve a deferred deep link suffix into a full URI, typically triggered during the first app launch after installation. ```APIDOC ## GET /api/v1/app/dynamic_link/{suffix} ### Description Resolves a deferred deep link suffix retrieved from the Install Referrer API into a functional URI for the application to handle. ### Method GET ### Endpoint /api/v1/app/dynamic_link/{suffix} ### Parameters #### Path Parameters - **suffix** (String) - Required - The unique identifier extracted from the install referrer. #### Query Parameters - **event_type** (String) - Required - The event context, typically set to "setup" for deferred deep link resolution. ### Response #### Success Response (200) - **resolvedUri** (String) - The deep link URI to be navigated to within the app. #### Response Example { "resolvedUri": "myapp://content/campaign-xyz" } ``` -------------------------------- ### Initialize and Listen for Deferred Deep Links in Kotlin Source: https://limelink.org/md/android-sdk Demonstrates the default automatic initialization of the LimeLink SDK and how to register a listener to handle deferred deep links received upon first launch. ```kotlin LimeLinkSDK.init(this, config) LimeLinkSDK.addLinkListener(object : LimeLinkListener { override fun onDeeplinkReceived(result: LimeLinkResult) { if (result.isDeferred) { navigateToContent(result.resolvedUri) } } }) ``` -------------------------------- ### Initialize LimeLink SDK in Objective-C Source: https://limelink.org/md/ios-sdk Configure and initialize the LimeLink SDK at application startup. Requires an API key and base URL. ```objective-c LimeLinkConfig *config = [[LimeLinkConfig alloc] initWithApiKey:@"YOUR_API_KEY" baseUrl:@"https://limelink.org/" loggingEnabled:YES deferredDeeplinkEnabled:YES]; [LimeLinkSDK initialize:config]; ``` -------------------------------- ### SDK Core Methods Source: https://limelink.org/md/android-sdk Core methods for initializing the LimeLink SDK and managing deep link listeners. ```APIDOC ## SDK Initialization and Listeners ### Description Methods to initialize the SDK and register listeners to handle incoming deep links. ### Methods - `LimeLinkSDK.init(context, config)`: Initializes the SDK. Should be called in `Application.onCreate()`. - `LimeLinkSDK.addLinkListener(listener)`: Registers a callback to receive `LimeLinkResult` objects. ### Request Example ```kotlin LimeLinkSDK.init(this, config) LimeLinkSDK.addLinkListener(object : LimeLinkListener { override fun onDeeplinkReceived(result: LimeLinkResult) { if (result.isDeferred) { navigateToContent(result.resolvedUri) } } }) ``` ``` -------------------------------- ### Initialize LimeLink SDK in Application Class Source: https://limelink.org/md/android-sdk This Kotlin code snippet shows how to initialize the LimeLink SDK within your `Application` class's `onCreate()` method. It includes configuration options for API key, logging, and deferred deeplinking. ```kotlin import org.limelink.limelink_aos_sdk.LimeLinkConfig import org.limelink.limelink_aos_sdk.LimeLinkSDK class MyApp : Application() { override fun onCreate() { super.onCreate() val config = LimeLinkConfig.Builder("YOUR_API_KEY") .setLogging(true) // Debug logs (default: false) .setDeferredDeeplinkEnabled(true) // Auto deferred deeplink check (default: true) // .setBaseUrl("https://custom.api.com/") // Custom server (default: https://limelink.org/) .build() LimeLinkSDK.init(this, config) } } ``` -------------------------------- ### Migrate Deep Link Handling from v0.0.x to v0.1.0+ (Kotlin) Source: https://limelink.org/md/android-sdk Demonstrates the migration of deep link handling from the older v0.0.x API to the new v0.1.0+ API in Kotlin. The new approach involves a one-time initialization in the Application class and registering a listener in Activities. ```kotlin // No Application-level initialization // Manual handling in each Activity class MyActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) LimeLinkSDK.handleUniversalLink(this, intent) { uri -> /* ... */ } saveLimeLinkStatus(this, intent, "api_key") } override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) LimeLinkSDK.handleUniversalLink(this, intent) { uri -> /* ... */ } } // Manual parsing val params = LimeLinkSDK.parseQueryParams(intent) val pathParams = UrlHandler.parsePathParams(intent) } ``` ```kotlin // One-time initialization in Application class MyApp : Application() { override fun onCreate() { super.onCreate() val config = LimeLinkConfig.Builder("api_key").build() LimeLinkSDK.init(this, config) } } // Register listener in Activity class MyActivity : Activity() { private val listener = object : LimeLinkListener { override fun onDeeplinkReceived(result: LimeLinkResult) { // All info is included in result: // result.originalUrl, result.resolvedUri // result.queryParams, result.pathParams // result.isDeferred, result.referrerInfo } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) LimeLinkSDK.addLinkListener(listener) } override fun onDestroy() { super.onDestroy() LimeLinkSDK.removeLinkListener(listener) } } ``` -------------------------------- ### Migrate to Limelink SDK v0.2.0 Source: https://limelink.org/md/ios-sdk Comparison of manual legacy implementation versus the automated v0.2.0 SDK initialization and listener pattern. ```swift // Before (Previous Versions) saveLimeLinkStatus(url: url, privateKey: "your_key") UniversalLink.shared.handleUniversalLink(url) { uri in if let uri = uri { // Handle URI } } if LinkStats.isFirstLaunch() { DeferredDeepLinkService.getDeferredDeepLink { result in switch result { case .success(let uri): // Handle URI case .failure(let error): // Handle error } } } ``` ```swift // After (v0.2.0) let config = LimeLinkConfig(apiKey: "your_key") LimeLinkSDK.initialize(config: config) class MyViewController: UIViewController, LimeLinkListener { override func viewDidLoad() { super.viewDidLoad() LimeLinkSDK.shared.addLinkListener(self) } func onDeeplinkReceived(result: LimeLinkResult) { // Handle result.resolvedUri, result.queryParams, result.pathParams } } func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { if let url = userActivity.webpageURL { LimeLinkSDK.shared.handleUniversalLink(url) return true } return false } ``` -------------------------------- ### Configure Application Class in AndroidManifest.xml Source: https://limelink.org/md/android-sdk This XML snippet shows how to register your custom Application class (e.g., `MyApp`) in the `AndroidManifest.xml` file. This is necessary for the SDK initialization to take place. ```xml ``` -------------------------------- ### Add JitPack Repository to Project Settings Source: https://limelink.org/md/android-sdk This snippet shows how to add the JitPack repository to your project's `settings.gradle` file. This is a prerequisite for including SDKs distributed via JitPack. ```groovy dependencyResolutionManagement { repositories { google() mavenCentral() maven { url 'https://jitpack.io' } } } ``` -------------------------------- ### Checking SDK Initialization Status Source: https://limelink.org/md/ios-sdk Demonstrates how to check if the LimeLink SDK has been successfully initialized using the `isInitialized` property. This check can be used to ensure SDK readiness before performing related operations. ```swift if LimeLinkSDK.shared.isInitialized { // SDK is ready } ``` -------------------------------- ### Handle Deep Links in ViewController Source: https://limelink.org/md/ios-sdk Demonstrates how to register a ViewController as a listener to process deep links and perform navigation. It distinguishes between deferred and standard deep links and provides error handling logic. ```Swift import UIKit import LimelinkIOSSDK class MainViewController: UIViewController, LimeLinkListener { override func viewDidLoad() { super.viewDidLoad() LimeLinkSDK.shared.addLinkListener(self) } func onDeeplinkReceived(result: LimeLinkResult) { guard let uri = result.resolvedUri else { return } if result.isDeferred { print("Deferred deep link: \(uri)") } else { print("Universal link resolved: \(uri)") } navigateToContent(uri: uri) } func onDeeplinkError(error: LimeLinkError) { print("Deeplink error [\(error.code)]: \(error.message)") } private func navigateToContent(uri: String) { guard let url = URL(string: uri) else { return } let pathComponents = url.pathComponents if pathComponents.contains("product"), let id = pathComponents.last { let vc = ProductViewController(productId: id) navigationController?.pushViewController(vc, animated: true) } } } ``` -------------------------------- ### Handle Universal Links in Objective-C Source: https://limelink.org/md/ios-sdk Implement universal link support within the AppDelegate. Provides methods to handle links directly via the SDK or through a bridge with completion handlers. ```objective-c - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray> *))restorationHandler { if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { NSURL *url = userActivity.webpageURL; if (url) { [[LimeLinkSDK shared] handleUniversalLink:url]; return YES; } } return NO; } ``` ```objective-c #import - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray> *))restorationHandler { if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { NSURL *url = userActivity.webpageURL; if (url) { [UniversalLinkHandlerBridge handleUniversalLink:url completion:^(NSString * _Nullable uri) { if (uri) { NSLog(@"Resolved URI: %@", uri); } }]; return YES; } } return NO; } ``` -------------------------------- ### POST /api/v1/core/link Source: https://limelink.org/md/api-integration Generates a dynamic link with various customization options for different platforms and analytics. ```APIDOC ## POST /api/v1/core/link ### Description This endpoint generates a dynamic link. It allows for detailed configuration of the link's behavior on different platforms (iOS, Android), preview appearance, and UTM parameters for tracking. ### Method POST ### Endpoint /api/v1/core/link ### Parameters #### Query Parameters None #### Request Body - **dynamic_link_suffix** (string) - Required - A unique suffix for the dynamic link. - **dynamic_link_url** (string) - Required - The base URL the dynamic link should resolve to. - **dynamic_link_name** (string) - Required - A descriptive name for the dynamic link. - **apple_options** (object) - Optional - Configuration for iOS specific behavior. - **application_id** (string) - Required (if apple_options is present) - The application ID for Apple. - **not_installed_options** (object) - Optional - Behavior when the app is not installed. - **custom_url** (string) - Required (if not_installed_options is present) - The URL to redirect to if the app is not installed. - **request_uri** (string) - Optional - The specific URI path for Apple devices. - **android_options** (object) - Optional - Configuration for Android specific behavior. - **application_id** (string) - Required (if android_options is present) - The application ID for Android. - **not_installed_options** (object) - Optional - Behavior when the app is not installed. - **custom_url** (string) - Required (if not_installed_options is present) - The URL to redirect to if the app is not installed. - **request_uri** (string) - Optional - The specific URI path for Android devices. - **additional_options** (object) - Optional - Additional customization options. - **preview_title** (string) - Optional - Title for link previews. - **preview_description** (string) - Optional - Description for link previews. - **preview_image_url** (string) - Optional - URL for the preview image. - **utm_source** (string) - Optional - UTM source parameter. - **utm_medium** (string) - Optional - UTM medium parameter. - **utm_campaign** (string) - Optional - UTM campaign parameter. - **project_id** (string) - Required - The ID of the project. - **stats_flag** (boolean) - Optional - Flag to enable/disable statistics tracking. ### Request Example ```json { "dynamic_link_suffix": "my-promo", "dynamic_link_url": "https://example.com/product/123", "dynamic_link_name": "My Product Promotion", "apple_options": { "application_id": "f8b2d4e1-9c7a-4f6e-b3d8-2a1e9c4f7b6d", "not_installed_options": { "custom_url": "https://apps.apple.com/app/id123456789" }, "request_uri": "product/123" }, "android_options": { "application_id": "a3f7c9b2-6e4d-4a8c-9f1b-8d5e2c9a7f3b", "not_installed_options": { "custom_url": "https://play.google.com/store/apps/details?id=com.example.androidapp" }, "request_uri": "product/123" }, "additional_options": { "preview_title": "Special Offer!", "preview_description": "Get 20% off on our new product.", "preview_image_url": "https://example.com/images/promo-preview.png", "utm_source": "newsletter", "utm_medium": "email", "utm_campaign": "q4_promo" }, "project_id": "project_abcdef123456", "stats_flag": true } ``` ### Response #### Success Response (200) - **link** (string) - The generated dynamic link. - **id** (string) - The unique identifier for the created link. #### Response Example ```json { "link": "https://yourdomain.page.link/AbCdEfG", "id": "link_xyz789" } ``` ### Security Warning > **⚠️ Important: API Key Security** ### Server-Side Only - **Do NOT expose your API key in client-side code** (JavaScript, mobile apps, etc.) - API keys should only be stored and used on your backend server - Client applications should call your own server, which then calls the LimeLink API ### Recommended Architecture ``` [Mobile App / Web Client] → [Your Backend Server] → [LimeLink API] ↑ API Key stored here ``` ### Why This Matters If your API key is exposed in client-side code: - Anyone can extract the key from your app or website - Unauthorized users can create links under your project - Your API quota may be exhausted by malicious actors ### Disclaimer **LimeLink is not responsible for any damages, unauthorized access, or misuse resulting from API key exposure.** Users are solely responsible for: - Securely storing and managing their API keys - Implementing proper server-side architecture - Any consequences arising from API key leakage or misuse By using this API, you acknowledge and accept full responsibility for the security of your API credentials. ### Notes - This API is typically used for in-app sharing and automated link generation - API access is project-based and secured via API keys - Rate limiting and validation rules may apply - More API endpoints may be added in future updates ``` -------------------------------- ### Configure SceneDelegate for Universal Links Source: https://limelink.org/md/ios-sdk Handles incoming Universal Links and Custom URL schemes within the SceneDelegate. It captures links during cold launches, warm launches, and via URL contexts to pass them to the LimeLinkSDK. ```Swift import LimelinkIOSSDK class SceneDelegate: UIResponder, UIWindowSceneDelegate { func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { if let userActivity = connectionOptions.userActivities.first, userActivity.activityType == NSUserActivityTypeBrowsingWeb, let url = userActivity.webpageURL { LimeLinkSDK.shared.handleUniversalLink(url) } } func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { if userActivity.activityType == NSUserActivityTypeBrowsingWeb, let url = userActivity.webpageURL { LimeLinkSDK.shared.handleUniversalLink(url) } } func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { if let url = URLContexts.first?.url { LimeLinkSDK.shared.handleUniversalLink(url) } } } ``` -------------------------------- ### Create Global DeepLinkManager Singleton Source: https://limelink.org/md/ios-sdk Implements a centralized manager to handle deep links app-wide using a singleton pattern. It broadcasts received links via NotificationCenter and ensures the listener remains active. ```Swift import LimelinkIOSSDK class DeepLinkManager: NSObject, LimeLinkListener { static let shared = DeepLinkManager() private override init() { super.init() LimeLinkSDK.shared.addLinkListener(self) } func onDeeplinkReceived(result: LimeLinkResult) { guard let uri = result.resolvedUri else { return } NotificationCenter.default.post( name: .didReceiveDeepLink, object: nil, userInfo: ["uri": uri, "isDeferred": result.isDeferred] ) } func onDeeplinkError(error: LimeLinkError) { print("[DeepLinkManager] Error: \(error.message)") } } extension Notification.Name { static let didReceiveDeepLink = Notification.Name("didReceiveDeepLink") } ``` -------------------------------- ### Troubleshoot 'Unresolved reference: LimeLinkSDK' with Gradle Source: https://limelink.org/md/android-sdk Provides commands to resolve the 'Unresolved reference: LimeLinkSDK' error when using JitPack. It involves ensuring the JitPack repository is added and refreshing the Gradle dependency cache. ```bash # If using JitPack — verify JitPack repository is added to settings.gradle # Refresh dependency cache ./gradlew clean --refresh-dependencies ``` -------------------------------- ### Universal Link and Custom URL Handling in AppDelegate Source: https://limelink.org/md/ios-sdk Implements methods in `AppDelegate` to handle both universal links and custom URL schemes by passing the incoming URL to `LimeLinkSDK.shared.handleUniversalLink()`. This ensures that deep links are correctly processed by the SDK. ```swift // MARK: - Universal Link Handling func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { if userActivity.activityType == NSUserActivityTypeBrowsingWeb, let url = userActivity.webpageURL { LimeLinkSDK.shared.handleUniversalLink(url) return true } return false } // MARK: - Custom URL Scheme Handling func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { LimeLinkSDK.shared.handleUniversalLink(url) return true } ``` -------------------------------- ### Universal Link Flow - Direct Access Pattern Source: https://limelink.org/md/android-sdk Describes the direct access pattern for Universal Links, where the SDK makes a direct API request to resolve a link. ```APIDOC ## GET /universal-link/app/dynamic_link/{suffix} ### Description This endpoint is an alternative path for the Universal Link flow, allowing direct API access to resolve a dynamic link using its suffix. ### Method GET ### Endpoint /universal-link/app/dynamic_link/{suffix} ### Parameters #### Path Parameters - **suffix** (string) - Required - The suffix of the dynamic link to resolve. #### Query Parameters - **full_request_url** (string) - Required - The full original URL that was clicked, including all query parameters. This must be URL-encoded. ### Request Example ``` GET /universal-link/app/dynamic_link/promo?full_request_url=https%3A%2F%2Fabc.limelink.org%2Flink%2Fpromo%3Fcampaign%3Dsummer%26source%3Demail ``` ### Response #### Success Response (200 OK) - **uri** (string) - The final, resolved URI that the SDK should navigate the user to. #### Response Example ```json { "uri": "https://example.com/products/promo-details?id=123" } ``` #### Error Response (400 Bad Request) - **error** (string) - A message indicating an issue with the request, such as an invalid or missing `full_request_url` parameter. #### Error Response Example ```json { "error": "Missing or invalid 'full_request_url' parameter." } ``` #### Error Response (404 Not Found) - **error** (string) - A message indicating that the dynamic link suffix could not be found or resolved. #### Error Response Example ```json { "error": "Dynamic link suffix 'promo' not found." } ``` ``` -------------------------------- ### Universal Link Flow - Subdomain Method Source: https://limelink.org/md/ios-sdk This method is recommended for handling universal links. The SDK intercepts clicks, extracts necessary information, and calls the API to resolve the final URI. ```APIDOC ## Universal Link Flow - Subdomain Method ### Description This method is recommended for handling universal links. The SDK intercepts clicks, extracts necessary information, and calls the API to resolve the final URI. ### Method GET ### Endpoint `https://{subdomain}.limelink.org/link/{linkSuffix}` `https://{subdomain}.limelink.org/link/{linkSuffix}?campaign=summer&source=email` ### Parameters #### Query Parameters - **campaign** (String) - Optional - Example query parameter. - **source** (String) - Optional - Example query parameter. - **full_request_url** (String) - Required - The full URL that was originally clicked, including all its query parameters. This is used by the API to reconstruct the context. ### Request Example ``` GET /api/v1/app/dynamic_link/test?full_request_url=https://abc.limelink.org/link/test?campaign=summer&source=email HTTP/1.1 Host: abc.limelink.org ``` ### Response #### Success Response (200) - **originalUrl** (String?) - The original URL that was opened. - **resolvedUri** (String?) - The final URI resolved by the API. - **queryParams** (Object) - URL query parameters. - **pathParams** (Object) - Path parameters (`mainPath`, `subPath`). - **isDeferred** (Boolean) - Whether this is a deferred deep link. #### Response Example ```json { "originalUrl": "https://abc.limelink.org/link/test?campaign=summer&source=email", "resolvedUri": "myapp://product/123", "queryParams": { "campaign": "summer", "source": "email" }, "pathParams": { "mainPath": "link", "subPath": "test" }, "isDeferred": false } ``` ``` -------------------------------- ### Info.plist URL Scheme Configuration Source: https://limelink.org/md/ios-sdk Registers a custom URL scheme in the application's `Info.plist` file. This is necessary for handling custom URL schemes used for deep linking. ```xml CFBundleURLTypes CFBundleURLName com.yourapp.deeplink CFBundleURLSchemes yourapp ``` -------------------------------- ### Create Dynamic Link Source: https://limelink.org/md/api-integration This endpoint allows you to create a new dynamic link. You can configure platform-specific options, deep linking behaviors, social preview content, and UTM parameters. ```APIDOC ## POST /api/v1/core/link ### Description Creates a new dynamic link with various configuration options for different platforms and tracking. ### Method POST ### Endpoint https://api.limelink.org/api/v1/core/link ### Headers - **X-API-KEY** (string) - Required - API key for project authentication - **Content-Type** (string) - Required - Must be `application/json` ### Request Body - **dynamic_link_suffix** (string, max 50) - Required - Unique identifier for the short URL path - **dynamic_link_url** (string, max 500) - Required - Target URL for desktop or fallback - **dynamic_link_name** (string, max 100) - Required - Link name for management and identification - **project_id** (string) - Required - Project ID the link belongs to - **stats_flag** (boolean) - Optional - Enable analytics tracking - **apple_options** (object) - Optional - Configuration for iOS platform - **application_id** (string, max 100) - Conditional - Application ID registered in the dashboard - **request_uri** (string) - Optional - Deep link path inside the app - **not_installed_options.custom_url** (string, max 500) - Conditional - Redirect URL when the app is not installed - **android_options** (object) - Optional - Configuration for Android platform - **application_id** (string, max 100) - Conditional - Application ID registered in the dashboard - **request_uri** (string) - Optional - Deep link path inside the app - **not_installed_options.custom_url** (string, max 500) - Conditional - Redirect URL when the app is not installed - **additional_options** (object) - Optional - Additional configuration for previews and tracking - **preview_title** (string, max 100) - Conditional - Social preview title - **preview_description** (string, max 200) - Conditional - Social preview description - **preview_image_url** (string, max 500) - Conditional - Social preview image URL - **utm_source** (string) - Optional - UTM source parameter - **utm_medium** (string) - Optional - UTM medium parameter - **utm_campaign** (string) - Optional - UTM campaign parameter ### Request Example ```json { "dynamic_link_suffix": "myuniquesuffix", "dynamic_link_url": "https://example.com/", "dynamic_link_name": "Example Link", "project_id": "your_project_id", "stats_flag": true, "apple_options": { "application_id": "123456789", "request_uri": "myapp://open/page", "not_installed_options": { "custom_url": "https://apps.apple.com/app/id123456789" } }, "android_options": { "application_id": "com.example.app", "request_uri": "myapp://open/page", "not_installed_options": { "custom_url": "https://play.google.com/store/apps/details?id=com.example.app" } }, "additional_options": { "preview_title": "Check out this link!", "preview_description": "A great link for you.", "preview_image_url": "https://example.com/image.png", "utm_source": "newsletter", "utm_medium": "email", "utm_campaign": "spring_promo" } } ``` ### Response #### Success Response (200) - **id** (string) - Unique identifier for the created dynamic link - **dynamic_link_suffix** (string) - The suffix of the dynamic link - **dynamic_link_url** (string) - The full dynamic link URL - **dynamic_link_name** (string) - The name of the dynamic link - **apple_options** (object) - Configuration for iOS platform - **android_options** (object) - Configuration for Android platform - **additional_options** (object) - Additional configuration options - **project_id** (string) - The project ID associated with the link - **stats_flag** (boolean) - Indicates if analytics tracking is enabled - **created_at** (string) - Timestamp when the link was created - **updated_at** (string or null) - Timestamp when the link was last updated #### Response Example ```json { "id": "link_abc123", "dynamic_link_suffix": "myuniquesuffix", "dynamic_link_url": "https://api.limelink.org/api/v1/core/link/myuniquesuffix", "dynamic_link_name": "Example Link", "apple_options": { "application_id": "123456789", "request_uri": "myapp://open/page", "not_installed_options": { "custom_url": "https://apps.apple.com/app/id123456789" } }, "android_options": { "application_id": "com.example.app", "request_uri": "myapp://open/page", "not_installed_options": { "custom_url": "https://play.google.com/store/apps/details?id=com.example.app" } }, "additional_options": { "preview_title": "Check out this link!", "preview_description": "A great link for you.", "preview_image_url": "https://example.com/image.png", "utm_source": "newsletter", "utm_medium": "email", "utm_campaign": "spring_promo" }, "project_id": "your_project_id", "stats_flag": true, "created_at": "2023-10-27T10:00:00Z", "updated_at": null } ``` ``` -------------------------------- ### Resolve CocoaPods build errors Source: https://limelink.org/md/ios-sdk Commands to resolve 'Module not found' errors by cleaning the CocoaPods environment and clearing Xcode derived data. ```bash pod deintegrate pod install rm -rf ~/Library/Developer/Xcode/DerivedData ``` -------------------------------- ### Create Dynamic Link via REST API Source: https://limelink.org/llms.txt The endpoint for programmatically generating dynamic links. Requires an API key passed in the request header for authentication. ```http POST https://api.limelink.org/api/v1/core/link Header: X-API-KEY: {your_api_key} ``` -------------------------------- ### Universal Link Flow - Subdomain Pattern Source: https://limelink.org/md/android-sdk Details the flow for Universal Links using the subdomain pattern, where the SDK extracts subdomain and link suffix to call the API. ```APIDOC ## GET /api/v1/app/dynamic_link/{suffix} ### Description This endpoint is part of the Universal Link flow. It is called by the SDK to resolve a dynamic link based on a provided suffix and query parameters, returning a resolved URI. ### Method GET ### Endpoint /api/v1/app/dynamic_link/{suffix} ### Parameters #### Path Parameters - **suffix** (string) - Required - The suffix of the dynamic link to resolve. #### Query Parameters - **full_request_url** (string) - Required - The full original URL that was clicked, including all query parameters. This must be URL-encoded. ### Request Example ``` GET /api/v1/app/dynamic_link/promo?full_request_url=https%3A%2F%2Fabc.limelink.org%2Flink%2Fpromo%3Fcampaign%3Dsummer%26source%3Demail ``` ### Response #### Success Response (200 OK) - **uri** (string) - The final, resolved URI that the SDK should navigate the user to. #### Response Example ```json { "uri": "https://example.com/products/promo-details?id=123" } ``` #### Error Response (400 Bad Request) - **error** (string) - A message indicating an issue with the request, such as an invalid or missing `full_request_url` parameter. #### Error Response Example ```json { "error": "Missing or invalid 'full_request_url' parameter." } ``` #### Error Response (404 Not Found) - **error** (string) - A message indicating that the dynamic link suffix could not be found or resolved. #### Error Response Example ```json { "error": "Dynamic link suffix 'promo' not found." } ``` ```