Click Analytics
Retrieve detailed click event data for any link. Every click is recorded with geographic, device, and referrer information.
The Click Object
Each click event contains the following fields:
| Field | Type | Description |
|---|---|---|
| id | string | Unique click event ID (UUID) |
| timestamp | string | ISO 8601 timestamp of when the click occurred |
| country | string | null | ISO 3166-1 alpha-2 country code (e.g. "US", "DE", "JP") |
| city | string | null | City name derived from geo-lookup |
| device | string | null | Device type: "desktop", "mobile", or "tablet" |
| os | string | null | Operating system (e.g. "Windows", "macOS", "iOS", "Android") |
| browser | string | null | Browser name (e.g. "Chrome", "Safari", "Firefox") |
| referrer | string | null | The referring URL (where the user came from) |
Privacy Note
IP addresses are used only for geo-lookup during the click event and are never stored in the analytics database. Flyn is fully GDPR compliant.
Get Click Events
Returns paginated click events for a specific link, ordered newest first.
GET/api/links/:id/clicks
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The UUID of the link |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| page | number | No | Page number (default: 1) |
| limit | number | No | Items per page (1-1000, default: 100) |
Request Example
curl "https://www.flyn.to/api/links/a1b2c3d4-.../clicks?page=1&limit=50" \ -H "Authorization: Bearer flyn_sk_live_..."
Response (200)
Response
{
"clicks": [
{
"id": "click-uuid-1",
"timestamp": "2026-03-30T14:22:05.000Z",
"country": "US",
"city": "San Francisco",
"device": "desktop",
"os": "macOS",
"browser": "Chrome",
"referrer": "https://twitter.com"
},
{
"id": "click-uuid-2",
"timestamp": "2026-03-30T14:18:30.000Z",
"country": "DE",
"city": "Berlin",
"device": "mobile",
"os": "iOS",
"browser": "Safari",
"referrer": null
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 1423,
"totalPages": 29,
"hasMore": true
}
}Error Codes
| Parameter | Type | Required | Description |
|---|---|---|---|
| 404 | error | No | Link not found or does not belong to your account |
| 429 | error | No | Rate limit exceeded (30 req/min) |
Data Retention
| Plan | Click Data Retention |
|---|---|
| Free | 30 days |
| Pro | Unlimited |
Real-Time Click Events
For real-time click tracking, use webhooks instead of polling. Subscribe to the link.click event to receive an HTTP POST to your endpoint within seconds of every click.
link.click Webhook Payload
{
"event": "link.click",
"timestamp": 1711929600000,
"data": {
"linkId": "a1b2c3d4-...",
"slug": "my-campaign",
"shortUrl": "https://flyn.to/my-campaign",
"country": "US",
"city": "San Francisco",
"device": "desktop",
"os": "macOS",
"browser": "Chrome",
"referrer": "https://twitter.com"
}
}SDK Example
TypeScript
async function getClicksCountsByCountry() {
const res = await flyn.links.clicks('34a63508-39b3-4d43-9b91-fabf76d3ad80', {
page: 1,
limit: 100,
});
// Aggregate by country
const byCountry = res.data.reduce((acc, c) => {
const country = c.country || 'Unknown';
acc[country] = (acc[country] || 0) + 1;
return acc;
}, {} as Record<string, number>);
console.log(byCountry);
// { US: 45, DE: 23, JP: 12, ... }
}
getClicksCountsByCountry();Was this page helpful? Spotted something wrong?