Data Export
Export your analytics for reporting, spreadsheets, BI tools or your own records.
What you can export
| What | Where | Format |
|---|---|---|
| Your whole workspace | Dashboard: Settings → Export | LinkForty bundle |
| A summary of a link's analytics | Dashboard: Analytics → Export CSV | CSV |
| In-app events | Dashboard: Events → Export CSV, or the API | CSV, JSON |
| Raw click events | API: GET /api/analytics/export | JSON, CSV |
| Your links | API: GET /api/links | JSON |
Exports contain the data your plan retains: 7 days of raw clicks on Free, 90 on Pro, 180 on Business and 365 on Unlimited. Owners, admins and members can export; viewers can't. API requests use an API key and count toward your plan's rate limits.
Your whole workspace
Settings → Export → Download export downloads the workspace's links, templates, clicks, installs, in-app events and webhooks in one file, for the period your plan keeps. Owners and admins can download it.
The file is a LinkForty bundle: gzipped, newline-delimited JSON with a checksum. A self-hosted LinkForty server imports it whole:
DATABASE_URL=postgres://... npx linkforty import linkforty-acme-2026-10-15.lfbundle --dry-run # check first
DATABASE_URL=postgres://... npx linkforty import linkforty-acme-2026-10-15.lfbundle
- Ids are kept, so links, clicks and installs stay connected, and your apps keep the install ids they already have.
- Webhook signing secrets aren't included. The import issues new ones and prints them.
- Some workspace data isn't in the bundle, because it has no equivalent on a self-hosted server:
- team members and roles;
- projects and custom domains;
- brand kit and social preview cards;
- web pixel events;
- billing.
- The file contains every click's IP address and user agent. Store it with the same care as your database.
From the dashboard
Analytics summary
On the Analytics page, pick a link (or all links) and a time range, then click Export CSV. The file holds what the page shows:
- summary metrics: total clicks, unique clicks, unique rate and average daily clicks;
- clicks per day;
- clicks by country, device and platform.
It is a report, not raw data. For one row per click, use the API.
In-app events
On the Events page, click Export CSV to download the events your apps have tracked, filtered as the page is.
Raw click events
GET /api/analytics/export returns one row per click, newest first, a page at a time.
curl "https://api.linkforty.com/api/analytics/export?startDate=2026-03-01&endDate=2026-03-31&limit=1000" \
-H "Authorization: Bearer $LINKFORTY_API_KEY"
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
startDate | ISO date or date-time | none | Clicks at or after this time |
endDate | ISO date or date-time | none | Clicks at or before this time |
linkId | UUID | all links | Only this link's clicks |
format | json or csv | json | Response format |
limit | 1–10,000 | 1,000 | Clicks per page |
offset | number | 0 | Clicks to skip, for the next page |
Without startDate and endDate, the export covers all the clicks your plan retains. The export includes links created in the dashboard and through the links API; links created by the mobile SDKs aren't included.
JSON response
{
"data": [
{
"id": "0b9d7c1e-5f3a-4c2b-9a8e-1d2c3b4a5f60",
"linkId": "6a1f0c2e-3b4d-4e5f-8a9b-0c1d2e3f4a5b",
"shortCode": "spring24",
"linkTitle": "Spring Sale",
"clickedAt": "2026-03-15T14:23:12.000Z",
"ipAddress": "203.0.113.24",
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) ...",
"deviceType": "ios",
"platform": "iOS",
"countryCode": "US",
"countryName": "United States",
"region": "California",
"city": "San Francisco",
"timezone": "America/Los_Angeles",
"latitude": 37.7749,
"longitude": -122.4194,
"utmSource": "instagram",
"utmMedium": "social",
"utmCampaign": "spring-sale",
"referrer": "https://www.instagram.com/",
"linkParams": { "fbclid": "IwAR..." },
"isBot": false
}
],
"pagination": { "total": 5432, "limit": 1000, "offset": 0, "hasMore": true }
}
CSV response. With format=csv, the response is a file download with one header row and one row per click, using the same field names. linkParams is written as JSON, and values containing commas, quotes or line breaks are quoted.
Fields
| Field | Description |
|---|---|
id | Click ID |
linkId, shortCode, linkTitle | The link that was clicked |
clickedAt | When the click happened (UTC) |
ipAddress, userAgent | The visitor's IP address and browser user agent |
deviceType, platform | Device and platform detected from the user agent |
countryCode, countryName, region, city, timezone, latitude, longitude | Location from the IP address |
utmSource, utmMedium, utmCampaign | UTM parameters on the click |
referrer | The referring page, when the browser sent one |
linkParams | Other query parameters the click arrived with, such as fbclid or gclid, or null |
isBot | Whether the click came from a bot or link previewer |
Fetching every page
async function exportAllClicks(startDate: string, endDate: string) {
const clicks = [];
let offset = 0;
const limit = 10000;
while (true) {
const response = await fetch(
`https://api.linkforty.com/api/analytics/export?startDate=${startDate}&endDate=${endDate}&limit=${limit}&offset=${offset}`,
{ headers: { Authorization: `Bearer ${process.env.LINKFORTY_API_KEY}` } }
);
const page = await response.json();
clicks.push(...page.data);
if (!page.pagination.hasMore) return clicks;
offset += limit;
}
}
New clicks arrive while you page, and pages are newest first, so for a stable export pass an endDate in the past.
In-app events
GET /api/analytics/events/export returns the events your apps tracked through the SDK, newest first.
| Parameter | Default | Description |
|---|---|---|
days | 30 | How many days back to include |
eventName | all events | Only this event |
format | json | json or csv |
limit, offset | 1,000, 0 | Paging, as for clicks |
Each event has id, eventName, eventData, eventTimestamp, installId, linkId, linkShortCode and linkTitle.
Links
GET /api/links lists your workspace's links, 100 per page at most. See List All Links for parameters and fields.
Troubleshooting
The export is empty. Check that the link has clicks in the date range and that the range falls within your plan's retention. Dates are compared in UTC.
Fewer rows than total. total counts every matching click; each response holds at most limit of them. Keep requesting with a larger offset until hasMore is false.
Garbled characters in a spreadsheet. The CSV is UTF-8. In Excel, use Data → From Text/CSV and choose UTF-8.