Deferred deep linking
Preserve the intended in-app destination when the user installs your app after tapping a Flinku link.
Overview
The user taps a short URL → store if needed → installs → opens the app. Flinku stores the click context and returns it on first match() so you can navigate to the same screen as if the app were already installed.
Requirements
- Universal Links (iOS) and App Links (Android) configured for your project host.
- SDK initialized with the correct
baseUrl. - User opens the link from a real browser or app context, not only by typing the URL.
Deferred match consumption
When the server successfully resolves a deferred link via match(), it marks that match as consumed. This behavior is server-side and applies to all SDKs (Flutter, iOS, Android, React Native, Capacitor, Unity) as of July 21, 2026 — no SDK update is required.
- First return consumes the match. The server records the match as delivered when it first returns a result to the app.
- 5-minute grace window. If the app calls
match()again within 5 minutes of the first successful return, the server returns the same match again. This covers app restarts mid flow so attribution is not lost. - After the grace window. Once 5 minutes have passed since the first successful return, the server will not return that match again, even if the client cache was cleared.
- Fingerprint attribution window. Fingerprint-based matching remains available for 24 hours from the original link click to the user's first app open. After 24 hours, fingerprint matching will not resolve the click.
SDK-local reset() clears the client match cache only; it does not undo server-side consumption.
Example (Flutter)
final link = await Flinku.match();if (link.matched && link.deepLink != null) {Navigator.pushNamed(context, link.deepLink!);}
match() vs resolving a short link
match() is for deferred deep linking: the user tapped a Flinku link before the app was installed. After install, the SDK asks the server for the install attribution match (fingerprint and clipboard on all SDKs at stable release; Play Install Referrer only on the native Android SDK and on Flutter 0.8.0-beta.1, which is a prerelease — stable 0.7.2 does not include it; opt in with flinku_sdk: 0.8.0-beta.1 in pubspec.yaml and rebuild the app) and returns that click's deep link and params.
Resolving a short link that an already installed user taps is a different job. When Universal Links or App Links open your app with a URL like https://yourapp.flku.dev/abc123, you already have the short URL. Call the public resolve endpoint to turn that slug into JSON (deepLink, params, title) without a browser redirect. No authentication required.
Use GET /api/links/resolve/:slug?subdomain=... for that path. Do not use match() for it.
Example: App Links → resolve
// Incoming App Link / Universal Link:// https://yourapp.flku.dev/abc123final uri = Uri.parse(incomingUrl);final subdomain = uri.host.split('.').first; // yourappfinal slug = uri.pathSegments.isNotEmpty ? uri.pathSegments.first : null;if (slug == null) return;final res = await http.get(Uri.parse('https://flku.dev/api/links/resolve/$slug?subdomain=$subdomain',),);if (res.statusCode != 200) return;final data = jsonDecode(res.body) as Map<String, dynamic>;final deepLink = data['deepLink'] as String?;final params = data['params'] as Map<String, dynamic>? ?? {};// Navigate using deepLink + params
Apps that already handle their own deep links
Many apps already route App Links, Universal Links, and URI schemes in their own navigator. That is Path A (direct). match() is Path B (deferred install attribution). They are not interchangeable.
Failure mode: the platform opens your app with a direct link, your app routes it correctly, then an unconditional match() returns a deferred result for the same (or another) click. If you treat both as one navigation source, the deferred result can overwrite the direct link and land the user on the wrong screen.
Recommendation: call match() only when no launch URL is present. If the OS (or your deep-link package) already delivered a URL, route that URL — resolve short Flinku URLs with GET /api/links/resolve — and skip match() for that open.
Troubleshooting
If Universal Links open the Flutter app but Dart never receives the URL (wrong screen, browser flash, or intermittent cold-start delivery), see Universal Links not opening the app on iOS (Flutter). Those failures are Flutter / iOS platform issues — Flinku links are ordinary Universal Links.