Creating links
Make short links from inside the app for share and invite flows with Lander.createLink.
Lander.createLink creates a Lander short link from the app, for example when someone taps Share on a product or Invite a friend. The link works like one made in the dashboard: it opens your app on the right screen, or sends people without the app to the store or your website.
Create a link
import 'package:flutter/services.dart';
import 'package:lander_flutter/lander_flutter.dart';
Future<void> shareProduct(BuildContext context, String id, String name) async {
final messenger = ScaffoldMessenger.of(context);
try {
final link = await Lander.createLink(
path: '/product/$id',
params: {'productId': id},
title: name,
channel: 'share',
);
await Clipboard.setData(ClipboardData(text: link.url.toString()));
messenger.showSnackBar(SnackBar(content: Text('Copied ${link.url}')));
} on LanderException catch (e) {
messenger.showSnackBar(SnackBar(content: Text('Could not create a link: ${e.message}')));
}
}link.url is the shareable URL, for example https://acme.golander.link/x7Kp2Qa. Hand it to the share sheet package you already use, or copy it as above.
When someone opens that link, your app receives a LanderLink with path == '/product/123' and params == {'productId': '123'}. See Receiving links.
Parameters
static Future<LanderShortLink> createLink({
String path = '/',
Map<String, Object> params = const {},
String? title,
String? campaign,
String? channel,
List<String> tags = const [],
Uri? iosFallbackUrl,
Uri? androidFallbackUrl,
Uri? webFallbackUrl,
String? ogTitle,
String? ogDescription,
Uri? ogImageUrl,
DateTime? expiresAt,
})Prop
Type
What you cannot choose from the app:
- The slug is always random (7 characters).
- The domain is the project's default domain.
- The environment follows the key: a
pk_test_key creates test links, apk_live_key creates live links.
Fallback URLs change deferred linking
A link with an Android fallback URL sends Android users without the app to that URL instead of the Play Store, so it cannot carry an install referrer token. Likewise an iOS fallback URL skips the Continue in app page. Leave them empty if you want deferred deep links. See Deferred links.
The result
createLink returns a LanderShortLink:
| Field | Type | Example |
|---|---|---|
id | String | Link ID (UUID) |
url | Uri | https://acme.golander.link/x7Kp2Qa |
domain | String | acme.golander.link |
slug | String | x7Kp2Qa |
path | String | /product/123 |
params | Map<String, Object> | {productId: 123} |
title, campaign, channel | String? | As sent |
tags | List<String> | As sent |
expiresAt, createdAt | DateTime? | Parsed from the API |
toString() returns the URL, so 'Check this out: $link' reads naturally.
Errors
createLink checks two things before it sends anything, and throws an ArgumentError when:
pathdoes not start with/.- A
paramsvalue is not aString,numorbool.
Everything else is checked by the API. Failures throw a LanderException:
code | statusCode | Meaning |
|---|---|---|
validation_error | 400 | A field is too long or malformed (see the limits above). |
destination_blocked | 400 | A fallback URL failed Lander's safety screening. |
rate_limited | 429 | Too many links from this install (20 per minute) or project (60 per minute). retryAfter says when to try again. |
link_quota_exceeded | 429 | The project created 1000 links in the last 24 hours. |
invalid_api_key | 401 | The publishable key is wrong or revoked. |
network_error, timeout | none | No response after retries. |
invalid_response | none | The response could not be parsed. |
e.isRetryable is true for network errors, timeouts, 408, 429 and 5xx responses.
Retries never create two links
The SDK retries network errors, timeouts, 408, 429 and 5xx responses up to 3 attempts in total, with a short backoff (and waits at least as long as a Retry-After header asks). Every attempt carries the same Idempotency-Key, and Lander replays the first successful response for a repeated key, so a retry after a lost response returns the same link instead of creating a second one.
The install ID is sent along, which is how the API applies the per install rate limit.