Links
Create, update, delete, and list short links. Supports custom slugs, domains, tags, passwords, expiration, smart routing, and custom OG metadata.
The Link Object
Every link endpoint returns the same standardized object shape:
| Field | Type | Description |
|---|---|---|
| id | string | Unique link ID (UUID) |
| slug | string | The short slug (e.g. "my-campaign") |
| url | string | The destination URL |
| shortUrl | string | Full short URL (e.g. "https://flyn.to/my-campaign") |
| domain | string | Domain used for this link |
| title | string | null | Display title for the link |
| clicks | number | Total click count |
| status | string | "active", "expired", or "archived" |
| tags | string[] | Array of tags for organizing links |
| createdAt | string | ISO 8601 creation timestamp |
| expiresAt | string | null | ISO 8601 expiration timestamp, or null |
| folderId | string | null | Folder ID if link is in a folder |
| password | boolean | Whether the link is password-protected (actual value is never exposed) |
| ogTitle | string | null | Custom Open Graph title |
| ogDescription | string | null | Custom Open Graph description |
| ogImage | string | null | Custom Open Graph image URL |
| targeting | object | null | Device/geo targeting rules (see Smart Routing below) |
| cloaking | boolean | Whether link cloaking is enabled |
| noIndex | boolean | Whether search engine indexing is blocked |
| notes | string | null | Private notes about the link |
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"slug": "my-campaign",
"url": "https://example.com/landing-page?utm_source=twitter",
"shortUrl": "https://flyn.to/my-campaign",
"domain": "www.flyn.to",
"title": "example.com",
"clicks": 1423,
"status": "active",
"tags": ["marketing", "q1-2026"],
"createdAt": "2026-03-15T10:30:00.000Z",
"expiresAt": null,
"folderId": null,
"password": false,
"ogTitle": "Check out our new product",
"ogDescription": "The fastest way to manage links",
"ogImage": "https://example.com/og-image.png",
"targeting": null,
"cloaking": false,
"noIndex": false,
"notes": null
}Create a Link
Creates a new short link. If no slug is provided, a random 6-character slug is generated.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | The destination URL to shorten. Auto-prepends https:// if no protocol is provided. |
| slug | string | No | Custom slug (letters, numbers, hyphens, underscores). Max 100 chars. Auto-generated if omitted. |
| domain | string | No | Domain to use (must be a verified custom domain). Defaults to "www.flyn.to". |
| title | string | No | Display title. Defaults to the destination hostname. |
| tags | string[] | No | Array of tags for organizing links. |
| password | string | No | Password-protect the link. Users must enter the password before being redirected. |
| expiresAt | string | No | ISO 8601 expiration date. Link returns 410 Gone after this date. |
| folderId | string | No | UUID of a folder to organize the link into. |
| ogTitle | string | No | Custom Open Graph title for link previews. |
| ogDescription | string | No | Custom Open Graph description for link previews. |
| ogImage | string | No | Custom Open Graph image URL. Must be public HTTPS URL. |
| targeting | object | No | Smart routing rules (see Smart Routing section below). |
| cloaking | boolean | No | Enable link cloaking, shows your short URL in the browser address bar. |
| noIndex | boolean | No | Add noindex meta tag to prevent search engines from indexing. |
| notes | string | No | Private notes about the link (not visible to clickers). |
curl -X POST https://www.flyn.to/api/links \
-H "Authorization: Bearer flyn_sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/landing-page",
"slug": "my-campaign",
"tags": ["marketing", "q1-2026"],
"ogTitle": "Check out our new product"
}'Response (201)
Returns the full Link object. Triggers link.create webhook event.
Error Codes
| Parameter | Type | Required | Description |
|---|---|---|---|
| 400 | error | No | Invalid URL, slug format, or missing required fields |
| 409 | error | No | Slug is already taken on this domain |
| 429 | error | No | Rate limit exceeded (10 req/min) |
List Links
Returns a paginated list of your links with optional filtering and sorting.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| page | number | No | Page number (default: 1) |
| limit | number | No | Items per page (1-100, default: 50) |
| status | string | No | Filter by status: "active", "expired", or "archived" |
| search | string | No | Search in slug, destination URL, and title |
| tag | string | No | Filter by tag name |
| folder_id | string | No | Filter by folder UUID |
| sort | string | No | Sort by: "created_at" (default), "clicks", "slug", or "title" |
| order | string | No | "asc" or "desc" (default: desc) |
curl "https://www.flyn.to/api/links?page=1&limit=20&status=active&tag=marketing&sort=clicks&order=desc" \ -H "Authorization: Bearer flyn_sk_live_..."
Response (200)
{
"links": [ /* array of Link objects */ ],
"pagination": {
"page": 1,
"limit": 20,
"total": 142,
"totalPages": 8,
"hasMore": true
}
}Get a Link
Retrieves a single link by ID.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The UUID of the link |
Returns the full Link object, or 404 if not found.
Update a Link
Updates one or more fields on an existing link. Only include the fields you want to change.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | No | New destination URL |
| slug | string | No | New slug (must be unique on the domain) |
| domain | string | No | New domain (must be a verified custom domain) |
| title | string | No | New display title |
| status | string | No | New status: "active", "expired", or "archived" |
| tags | string[] | No | Replace all tags |
| password | string | No | Set or update password |
| expiresAt | string | No | New expiration date (ISO 8601) |
| folderId | string | No | Move to a different folder |
| ogTitle | string | No | Update custom OG title |
| ogDescription | string | No | Update custom OG description |
| ogImage | string | No | Update custom OG image URL |
| targeting | object | No | Update smart routing rules |
| cloaking | boolean | No | Enable/disable link cloaking |
| noIndex | boolean | No | Enable/disable noindex |
| notes | string | No | Update private notes |
curl -X PATCH https://www.flyn.to/api/links/a1b2c3d4-... \
-H "Authorization: Bearer flyn_sk_live_..." \
-H "Content-Type: application/json" \
-d '{ "tags": ["marketing", "updated"], "status": "archived" }'Returns the updated Link object. Triggers link.update webhook event.
Delete a Link
Permanently deletes a link and all associated click data. This action cannot be undone.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The UUID of the link to delete |
Response (200)
{ "deleted": true, "id": "a1b2c3d4-..." }Triggers link.delete webhook event with the full link data that was deleted.
Smart Routing (Targeting)
The targeting field lets you redirect users to different destinations based on their device type or geographic location. Pass it as a JSON object when creating or updating a link.
{
"targeting": {
"ios": "https://apps.apple.com/app/your-app",
"android": "https://play.google.com/store/apps/details?id=your.app",
"desktop": "https://yoursite.com/desktop-landing",
"geo": {
"US": "https://yoursite.com/us",
"DE": "https://yoursite.com/de",
"JP": "https://yoursite.com/jp"
}
}
}Device targeting uses the ios, android, and desktop keys. Geo targeting uses ISO 3166-1 alpha-2 country codes. If no rule matches, the default url is used.
Slug Rules
- Allowed characters:
a-z A-Z 0-9 - _ - Maximum length: 100 characters
- Must be unique per domain (you can reuse slugs across different domains)
- Reserved slugs (e.g.
api,login,docs) cannot be used - If omitted, a random 6-character slug is generated using nanoid
SDK Examples
const link = await flyn.links.create({
url: 'https://example.com/my-long-url',
slug: 'my-campaign',
domain: 'go.yourcompany.com',
tags: ['marketing', 'q1-2026'],
ogTitle: 'Check out our product',
});
console.log(link.shortUrl);
// → https://go.yourcompany.com/my-campaignasync function getUrlWithClicks() {
const res = await flyn.links.list({
status: 'active',
tag: 'marketing',
sort: 'clicks',
order: 'desc',
limit: 20,
});
res.data.forEach(l => console.log(l.shortUrl, l.clicks));
}
getUrlWithClicks();Was this page helpful? Spotted something wrong?