Flinku Docs

API Reference

Base URL: https://flku.dev

Link management and match APIs are scoped to a project. Public short links and well-known files (Universal Links / App Links) are served on https://<subdomain>.flku.dev.

Authentication

Flinku supports two authentication methods:

1. Firebase ID Token (dashboard users)

bash
Authorization: Bearer <firebase-id-token>

2. API Key (programmatic access)

bash
Authorization: Bearer flk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Get your API key from your project Settings in the dashboard.

Create a link (example)

Example against the public API host. Replace flk_live_your_api_key with your key.

bash
POST https://flku.dev/api/links
Authorization: Bearer flk_live_your_api_key
Content-Type: application/json

Request body

javascript
{
"projectId": "YOUR_PROJECT_ID",
"title": "Summer Campaign",
"deepLink": "yourapp://promo",
"params": { "ref": "instagram", "promo": "SAVE20" },
"utmSource": "instagram",
"utmMedium": "social",
"utmCampaign": "summer_sale",
"desktopUrl": "https://yourwebsite.com/promo",
"expiresAt": "2026-12-31T00:00:00Z",
"maxClicks": 1000
}

Bulk link creation (JSON)

bash
POST https://flku.dev/api/links/bulk
Authorization: Bearer flk_live_your_api_key
Content-Type: application/json
javascript
{
"projectId": "your_project_id",
"links": [
{ "title": "Link 1", "deepLink": "yourapp://screen1" },
{ "title": "Link 2", "deepLink": "yourapp://screen2" }
]
}

Bulk import (CSV)

bash
POST https://flku.dev/api/links/bulk-csv
Authorization: Bearer flk_live_your_api_key
Content-Type: multipart/form-data

Form fields: file (CSV), projectId. Response includes created, skipped, errors, and links.

Creating links from the SDK

Flutter SDK 0.7.0+ and native mobile SDKs (iOS 0.7.0+, Android 0.7.0+, React Native 0.7.1+, Capacitor 0.7.1+, Unity 0.7.0+) can create short links in-app using your project baseUrl and API key.

⚠️ Never ship API keys in mobile appsAPI keys can be extracted from any compiled APK or .ipa. If your key leaks, attackers can spam-create links until your project hits its plan limits or gets flagged for abuse.

Correct architecture: Keep the API key on your own backend. Your app calls your backend, your backend calls Flinku, your backend returns the short URL to your app.

App → Your Backend → Flinku API → short URL → App shares it

Flutter

dart
// Configure once at app startup with your API key
Flinku.configure(
baseUrl: 'https://yourapp.flku.dev',
apiKey: 'flk_live_your_api_key',
);
 
// Then create links anywhere using the static method
final link = await Flinku.createLink(FlinkuLinkOptions(
title: 'Summer Campaign',
deepLink: 'yourapp://promo',
params: {'ref': 'instagram', 'promo': 'SAVE20'},
utmSource: 'instagram',
utmMedium: 'social',
));
 
print(link.shortUrl); // https://yourapp.flku.dev/summer-campaign

iOS (Swift)

swift
var options = FlinkuLinkOptions(title: "Summer Campaign")
options.deepLink = "yourapp://promo"
options.params = ["ref": "instagram"]
 
flinku.createLink(options) { result in
switch result {
case .success(let link):
print(link.shortUrl)
case .failure(let error):
print(error)
}
}

Android (Kotlin)

kotlin
val link = flinku.createLink(FlinkuLinkOptions(
title = "Summer Campaign",
deepLink = "yourapp://promo",
params = mapOf("ref" to "instagram")
))
println(link.shortUrl)

createLinkInstant() returns the short URL instantly without waiting for the server. The link is saved in the background. Use this for share buttons where speed matters.

Flutter

dart
import 'package:share_plus/share_plus.dart';
 
final link = Flinku.createLinkInstant(FlinkuLinkOptions(
title: 'Summer Campaign',
deepLink: 'yourapp://promo',
));
await Share.share(link.shortUrl);

iOS (Swift)

swift
let link = try Flinku.createLinkInstant(options)
let activityVC = UIActivityViewController(activityItems: [link.shortUrl], applicationActivities: nil)

Android (Kotlin)

kotlin
val link = Flinku.createLinkInstant(FlinkuLinkOptions(title = "Summer Campaign"))
val sendIntent = Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
putExtra(Intent.EXTRA_TEXT, link.shortUrl)
}
startActivity(Intent.createChooser(sendIntent, null))
POST/api/links

Create a new short link in the authenticated project. Supports attribution, expiry limits, passwords, geo routing, scheduled activation, smart fallback chain, and social preview metadata.

Auth: Required

FieldTypeDescription
projectIdstring (required)Project ID that owns this link
titlestring (required)Human-readable link title
deepLinkstring (optional)In-app route like yourapp://product/42
paramsobject (optional)Custom key-value payload
slugstring (optional)Custom slug for short URL
desktopUrlstring (optional)Desktop redirect URL
utmSourcestring (optional)UTM source value
utmMediumstring (optional)UTM medium value
utmCampaignstring (optional)UTM campaign value
utmContentstring (optional)UTM content value
utmTermstring (optional)UTM term value
expiresAtISO date string (optional)Link expiration datetime
maxClicksnumber (optional)Maximum click count before expiry
passwordstring (optional)Password required before redirect
scheduledAtISO date string (optional)When the link becomes active
geoRoutingarray (optional)Up to 10 rules: { countries, url }
fallbackChainstring[] (optional)Up to 3 HTTPS URLs for HEAD probe chain
influencerIdstring (optional)Attribution id for influencer reporting
ogTitlestring (optional)Open Graph title override
ogDescriptionstring (optional)Open Graph description override
ogImageUrlstring (optional)Open Graph image URL override
javascript
{
"success": true,
"slug": "abc123",
"shortUrl": "https://yourapp.flku.dev/abc123",
"link": {
"projectId": "YOUR_PROJECT_ID",
"title": "Spring Sale",
"deepLink": "yourapp://promo/spring"
}
}
POST/api/links/bulk

Create multiple links in a single JSON request. Maximum 100 links per request.

Auth: Required

FieldTypeDescription
projectIdstringProject ID for all links in this request
links[]arrayArray of up to 100 link definitions
links[].titlestringLink title
links[].deepLinkstring (optional)Deep link URI
links[].paramsobject (optional)Custom key-value params
links[].desktopUrlstring (optional)Desktop redirect URL
links[].utmSourcestring (optional)UTM source value
links[].utmMediumstring (optional)UTM medium value
links[].utmCampaignstring (optional)UTM campaign value
links[].expiresAtISO date string (optional)Link expiration datetime
links[].maxClicksnumber (optional)Maximum click count
links[].passwordstring (optional)Password protection
javascript
{
"created": 2,
"links": [
{ "slug": "abc123", "shortUrl": "https://myapp.flku.dev/abc123" },
{ "slug": "def456", "shortUrl": "https://myapp.flku.dev/def456" }
]
}
POST/api/links/bulk-csv

Import links from a CSV file. Maximum 400 rows and 1MB per upload. See Bulk Import (CSV) in the docs for column definitions.

Auth: Required

FieldTypeDescription
filefile (required)CSV upload
projectIdstring (required)Target project id
javascript
{
"created": 120,
"skipped": 3,
"errors": [{ "row": 45, "message": "Invalid slug" }],
"links": []
}
GET/api/links

List all links for the authenticated project.

Auth: Required

javascript
[
{
"slug": "abc123",
"title": "Spring Sale",
"shortUrl": "https://yourapp.flku.dev/abc123"
}
]
GET/api/links/:slug

Fetch one link by slug within the current project.

Auth: Required

javascript
{
"slug": "abc123",
"title": "Spring Sale",
"fallbackUrl": "https://www.flinku.dev",
"deepLink": "yourapp://promo/spring"
}
GET/api/links/:id/history

Returns the last 20 clicks for the link, including redirect chain details when available.

Auth: Required

javascript
[
{
"clickedAt": "2026-03-01T12:00:00.000Z",
"country": "US",
"redirectChain": ["https://yourapp.flku.dev/x", "https://apps.apple.com/..."]
}
]
POST/api/links/:id/clone

Clone a link with all settings (tags, campaigns, routing, etc.). Returns the new link record.

Auth: Required

javascript
{
"success": true,
"link": {
"slug": "cloned-abc",
"shortUrl": "https://yourapp.flku.dev/cloned-abc",
"title": "Spring Sale (copy)"
}
}
GET/api/links/:id/qr

Get the QR code payload for a link as base64 data URL.

Auth: Required

javascript
{
"qrCode": "data:image/png;base64,...",
"shortUrl": "https://myapp.flku.dev/abc123"
}
GET/api/links/:id/qr/png

Download QR code as a PNG image file.

Auth: Required

javascript
HTTP/1.1 200 OK
Content-Type: image/png
Content-Disposition: attachment; filename="abc123.png"
PUT/api/links/:slug

Update mutable fields for an existing link.

Auth: Required

FieldTypeDescription
updatable fieldsobjectAny fields accepted by create API
javascript
{
"success": true,
"link": {
"slug": "abc123",
"title": "Spring Sale Extended"
}
}
DELETE/api/links/:slug

Delete an existing link.

Auth: Required

javascript
{
"success": true
}
GET/api/links/resolve/:slug?subdomain=...

Public JSON lookup for an already-installed app that received a Flinku short URL over Universal Links or App Links. Returns the slug, deepLink, params, and title without redirecting. No authentication required. Distinct from POST /api/match, which resolves deferred install attribution.

Auth: None

FieldTypeDescription
slugpath (required)Short link slug, e.g. abc123 from https://yourapp.flku.dev/abc123
subdomainquery (required)Project subdomain, e.g. yourapp
javascript
// 200 OK
{
"slug": "abc123",
"deepLink": "yourapp://product/42",
"params": { "ref": "instagram", "promo": "SAVE20" },
"title": "Spring Sale"
}
 
// 400 Bad Request — missing slug or subdomain
{ "error": "slug and subdomain are required" }
 
// 404 Not Found — no link for that slug + subdomain
{ "error": "Link not found" }
GET/:slug

On the project host (yourapp.flku.dev), resolves the slug and redirects, typically to the App Store, Play Store, or in-app destination.

Auth: None

javascript
HTTP/1.1 302 Found
Location: https://apps.apple.com/...
POST/api/match

Resolve pending deferred deep links for SDK clients scoped to the project behind the request host or device session.

Auth: None

FieldTypeDescription
deviceInfoobject{ userAgent, timestamp }
javascript
{
"matched": true,
"deepLink": "yourapp://product/42",
"params": { "ref": "instagram", "promo": "SAVE20" },
"slug": "abc123",
"subdomain": "yourapp",
"title": "Spring Sale",
"projectId": "YOUR_PROJECT_ID",
"clickedAt": "2026-03-25T12:00:00.000Z"
}

Campaigns API

GET/api/campaigns?projectId=X

List campaigns for the given project.

Auth: Required

javascript
[
{
"id": "camp_abc123",
"projectId": "YOUR_PROJECT_ID",
"name": "Summer 2026",
"description": "Paid social"
}
]
POST/api/campaigns

Create a campaign container for grouping links.

Auth: Required

FieldTypeDescription
projectIdstring (required)Owning project
namestring (required)Campaign name
descriptionstring (optional)Internal notes
javascript
{
"success": true,
"campaign": {
"id": "camp_new",
"projectId": "YOUR_PROJECT_ID",
"name": "Spring Launch",
"description": "EU + US paid social"
}
}

Analytics API

GET/api/analytics/influencers?projectId=X

Aggregated clicks, installs, and unique users per influencerId for the project.

Auth: Required

javascript
[
{
"influencerId": "john_doe",
"clicks": 1200,
"installs": 80,
"uniqueUsers": 950
}
]

Projects API

GET/health

Health check endpoint for uptime monitoring.

Auth: None

javascript
{
"status": "ok",
"timestamp": 1710012345678,
"uptime": 15423.22
}
GET/api/projects/:id/journey.js

Public JavaScript bundle for the Journeys web banner. Embed the snippet from the dashboard or load this URL directly.

Auth: None

javascript
HTTP/1.1 200 OK
Content-Type: application/javascript
 
/* Hosted Journeys bootstrap */
PATCH/api/projects/:id/members/:uid

Update a team member's role (project owner / admin actions).

Auth: Required

FieldTypeDescription
role'editor' | 'viewer'New role for the Firebase uid
javascript
{
"success": true,
"member": {
"uid": "firebase_uid",
"role": "editor"
}
}

Referrals API

POST/api/referrals/track

Record that a new user came from a referral link. Flinku.setUserId calls this automatically when a pending referrerId exists. Do not call this by hand from the app.

Auth: API key or Firebase ID token

FieldTypeDescription
projectIdstring (required)Flinku project id
referrerIdstring (required)User id of the referrer (matches params.referrerId on the link)
newUserIdstring (required for API key auth)Id of the new user
referrerLabelstring (optional)Readable referrer name
linkIdstring (optional)Matched link id
javascript
{
"status": "attributed",
"flagReason": null
}
POST/api/referrals/qualify

Mark a referred user as qualified. Prefer Flinku.qualifyReferral.

Auth: API key or Firebase ID token

FieldTypeDescription
projectIdstring (required)Flinku project id
newUserIdstring (required for API key auth)Id of the new user
eventstring (optional)Defaults to default
javascript
{
"status": "qualified",
"flagReason": null,
"qualifyEvent": "purchase"
}
GET/api/referrals?projectId=X&range=7d|30d|all

Funnel and referrer table for the project.

Auth: Required

javascript
{
"range": "30d",
"funnel": { "clicks": 1200, "installs": 340, "qualified": 95, "clickToInstallRate": 0.28 },
"flaggedCount": 12,
"referrers": [{ "referrerId": "user_123", "referrerLabel": "Alice", "clicks": 40, "installs": 10, "qualified": 4, "flagged": 0 }]
}
GET/api/referrals/stats?projectId=X

Aggregate referral statistics for the project.

Auth: Required

javascript
{
"totalReferrals": 500,
"uniqueReferrers": 120,
"topReferrer": "user_123"
}

Firebase migration API

POST/api/migration/preview

Parse a legacy Firebase Dynamic Link URL and preview how it maps to Flinku fields (no links created).

Auth: None

FieldTypeDescription
firebaseLinkstring (required)Full Firebase Dynamic Link URL to inspect
javascript
{
"deepLink": "yourapp://screen",
"ogTitle": "Promo",
"ogDescription": "Summer sale",
"utmSource": "email",
"utmMedium": "newsletter",
"utmCampaign": "june"
}
POST/api/migration/convert

Bulk-create Flinku short links from an array of Firebase Dynamic Link URLs for the given project.

Auth: Required

FieldTypeDescription
firebaseLinksstring[] (required)List of Firebase Dynamic Link URLs to convert
projectIdstring (required)Target Flinku project
javascript
{
"converted": 48,
"failed": 2,
"links": []
}

Retargeting pixel

GET/api/pixel/:projectId

Retargeting pixel: returns a 1×1 transparent GIF and records that the device visited the embedding website (no cookies, no personal data in the pixel itself). Use for matching link clickers to prior site visits.

Auth: None

javascript
HTTP/1.1 200 OK
Content-Type: image/gif
 
GIF89a… (1×1 transparent)

Public URL pattern: https://flku.dev/api/pixel/YOUR_PROJECT_ID (same path on your API host when self-hosting).

ℹ️Info
Authenticated routes accept either a Firebase ID token or an API key in the Authorization: Bearer header, depending on your integration.