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:

FieldTypeDescription
idstringUnique link ID (UUID)
slugstringThe short slug (e.g. "my-campaign")
urlstringThe destination URL
shortUrlstringFull short URL (e.g. "https://flyn.to/my-campaign")
domainstringDomain used for this link
titlestring | nullDisplay title for the link
clicksnumberTotal click count
statusstring"active", "expired", or "archived"
tagsstring[]Array of tags for organizing links
createdAtstringISO 8601 creation timestamp
expiresAtstring | nullISO 8601 expiration timestamp, or null
folderIdstring | nullFolder ID if link is in a folder
passwordbooleanWhether the link is password-protected (actual value is never exposed)
ogTitlestring | nullCustom Open Graph title
ogDescriptionstring | nullCustom Open Graph description
ogImagestring | nullCustom Open Graph image URL
targetingobject | nullDevice/geo targeting rules (see Smart Routing below)
cloakingbooleanWhether link cloaking is enabled
noIndexbooleanWhether search engine indexing is blocked
notesstring | nullPrivate notes about the link
Example Link Object
{
  "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.

POST/api/links

Request Body

ParameterTypeRequiredDescription
urlstringYesThe destination URL to shorten. Auto-prepends https:// if no protocol is provided.
slugstringNoCustom slug (letters, numbers, hyphens, underscores). Max 100 chars. Auto-generated if omitted.
domainstringNoDomain to use (must be a verified custom domain). Defaults to "www.flyn.to".
titlestringNoDisplay title. Defaults to the destination hostname.
tagsstring[]NoArray of tags for organizing links.
passwordstringNoPassword-protect the link. Users must enter the password before being redirected.
expiresAtstringNoISO 8601 expiration date. Link returns 410 Gone after this date.
folderIdstringNoUUID of a folder to organize the link into.
ogTitlestringNoCustom Open Graph title for link previews.
ogDescriptionstringNoCustom Open Graph description for link previews.
ogImagestringNoCustom Open Graph image URL. Must be public HTTPS URL.
targetingobjectNoSmart routing rules (see Smart Routing section below).
cloakingbooleanNoEnable link cloaking, shows your short URL in the browser address bar.
noIndexbooleanNoAdd noindex meta tag to prevent search engines from indexing.
notesstringNoPrivate notes about the link (not visible to clickers).
Request Example
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

ParameterTypeRequiredDescription
400errorNoInvalid URL, slug format, or missing required fields
409errorNoSlug is already taken on this domain
429errorNoRate limit exceeded (10 req/min)

List Links

Returns a paginated list of your links with optional filtering and sorting.

GET/api/links

Query Parameters

ParameterTypeRequiredDescription
pagenumberNoPage number (default: 1)
limitnumberNoItems per page (1-100, default: 50)
statusstringNoFilter by status: "active", "expired", or "archived"
searchstringNoSearch in slug, destination URL, and title
tagstringNoFilter by tag name
folder_idstringNoFilter by folder UUID
sortstringNoSort by: "created_at" (default), "clicks", "slug", or "title"
orderstringNo"asc" or "desc" (default: desc)
Request Example
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)

Response
{
  "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.

GET/api/links/:id

Path Parameters

ParameterTypeRequiredDescription
idstringYesThe 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.

PATCH/api/links/:id

Request Body

ParameterTypeRequiredDescription
urlstringNoNew destination URL
slugstringNoNew slug (must be unique on the domain)
domainstringNoNew domain (must be a verified custom domain)
titlestringNoNew display title
statusstringNoNew status: "active", "expired", or "archived"
tagsstring[]NoReplace all tags
passwordstringNoSet or update password
expiresAtstringNoNew expiration date (ISO 8601)
folderIdstringNoMove to a different folder
ogTitlestringNoUpdate custom OG title
ogDescriptionstringNoUpdate custom OG description
ogImagestringNoUpdate custom OG image URL
targetingobjectNoUpdate smart routing rules
cloakingbooleanNoEnable/disable link cloaking
noIndexbooleanNoEnable/disable noindex
notesstringNoUpdate private notes
Request Example
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.

DELETE/api/links/:id

Path Parameters

ParameterTypeRequiredDescription
idstringYesThe 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 Object Example
{
  "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

TypeScript, Create a Link
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-campaign
TypeScript, List Links with Filters
async 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?