REST API
Programmatically create smart links and pull click analytics. All endpoints are under /api/v1 and authenticated with your project API key.
Prefer an interactive spec? See the API Reference or download openapi.yaml.
Authentication
Send your project API key (found on the project page) as a bearer token or an x-api-key header.
curl https://your-domain.com/api/v1/links \ -H "Authorization: Bearer lk_your_api_key"
/api/v1/linksCreate a smart link. Only fallbackUrl is required.
curl -X POST https://your-domain.com/api/v1/links \
-H "Authorization: Bearer lk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"title": "Spring sale",
"fallbackUrl": "https://shop.example.com/spring",
"iosUrl": "https://apps.apple.com/app/id123456789",
"androidUrl": "https://play.google.com/store/apps/details?id=com.acme.app",
"deepLinkPath": "/products/123",
"data": { "campaign": "spring", "product_id": "123" },
"channel": "email",
"campaign": "spring_sale",
"tags": ["promo", "q2"]
}'Response 201
{
"id": "clx...",
"slug": "ab12cd3",
"url": "https://your-domain.com/l/ab12cd3",
"fallbackUrl": "https://shop.example.com/spring",
...
}/api/v1/linksList links (newest first). ?limit=50
{ "data": [ { "id": "...", "slug": "ab12cd3", "url": "...", "clicks": 42 } ] }/api/v1/links/:idFetch a single link with its click count.
/api/v1/links/:idDelete a link permanently.
{ "deleted": true }/api/v1/links/:id/statsClick analytics for a link. ?days=30 (1–365).
{
"total": 128,
"unique": 96,
"byPlatform": [ { "name": "ios", "value": 70 }, { "name": "android", "value": 40 } ],
"byOs": [ ... ],
"byReferrer": [ ... ],
"timeseries": [ { "date": "2026-05-01", "clicks": 4 } ]
}How redirection works
- Visiting
/l/:slugdetects the device from the User-Agent. - Desktop visitors are 302-redirected to the desktop/fallback URL.
- Mobile visitors get an interstitial that attempts to open your app via its custom scheme + deep-link path, then falls back to the App Store / Play Store.
- Every visit is recorded with platform, OS, referrer and a hashed IP.
Keys: secret vs publishable
apiKey— secret, server-side only. Full REST API (list, stats, delete).sdkKey— publishable, safe to embed in the Web / Android / iOS SDKs. Can open sessions and create links.
SDKs — reading attributes in your app
The redirect engine gets users to your app; the SDKs deliver the link's attributes into it — including deferred deep linking, where data survives an App Store / Play Store install. Each SDK is a thin client over the session endpoint below.
- Web:
/sdk/linkly.js— try it on the live demo. - Android (Kotlin) and iOS (Swift) — see
/sdkin the repo.
<script src="/sdk/linkly.js"></script>
<script>
Linkly.init({ key: "<sdkKey>" }).then(function (session) {
if (session.matched) {
console.log("deep link data:", session.data);
// route with session.deepLinkPath
}
});
</script>Smart App Banner
Show a Branch-style "Open in app" bar on the mobile web that deep-links into the native app (with App/Play Store fallback). Hidden on desktop by default; dismissal is remembered.
Linkly.init({ key: "<sdkKey>" }).then(function () {
Linkly.banner({
title: "Acme Mobile",
text: "Open this in the app for the full experience.",
button: "Open",
position: "bottom", // or "top"
forDays: 7 // remember dismissal
});
});/api/v1/openOpen a session / match a deep link. Direct (with link) or deferred (by fingerprint). Used by every SDK.
curl -X POST https://your-domain.com/api/v1/open \
-H "Content-Type: application/json" \
-d '{ "key": "<sdkKey>", "platform": "ios", "link": "welcome" }'Response
{
"matched": true,
"is_first_session": true, // true on a deferred (post-install) match
"is_deferred": true,
"link": { "slug": "welcome", "url": "...", "title": "..." },
"deepLinkPath": "/products/123",
"data": { "product_id": "123", "~campaign": "spring_sale" },
"routing": { "fallbackUrl": "...", "iosUrl": "...", "androidUrl": "..." }
}Omit link for deferred matching: the server pairs the request's IP + platform with a recent click (≤ 60 min) and returns its attributes once.