Documentation

Everything you need to integrate ilync — from a first API call to authentication, rate limits, private links, and analytics.

Overview

ilync turns long URLs into short, shareable codes and redirects visitors to the original destination. Use it from the browser or programmatically over a small JSON API.

Instant shorteningAccounts & dashboardOptional expirationClick analyticsAPI keysRate limitingPrivate linksLight & dark themes

Quick start

ilync is a hosted HTTP service, so there is nothing to install or deploy to start using it. Point your application at the API and you can create short links in minutes. Every endpoint accepts and returns JSON over HTTPS.

Base URL. All API paths are relative to https://ilync.dev, used throughout the examples below.

1. Get an API key (recommended)

Anonymous requests work out of the box with a lower rate limit. For higher limits, link ownership, and private links, sign in and create a key under Developer API, then send it as a bearer token on each request. Store it as a secret in your backend — never ship it in client-side code.

2. Create your first short link

Send a POST to /api/urls with the URL to shorten. The Authorization header is optional but recommended for production integrations.

cURL
curl -X POST https://ilync.dev/api/urls \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer ilk_your_key_here' \
  -d '{"url":"https://example.com/a/very/long/path"}'
JavaScript (fetch)
const res = await fetch("https://ilync.dev/api/urls", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: "Bearer ilk_your_key_here", // optional
  },
  body: JSON.stringify({ url: "https://example.com/a/very/long/path" }),
});

if (!res.ok) throw new Error(`ilync error: ${res.status}`);

const { shortUrl } = await res.json();
console.log(shortUrl); // → https://ilync.dev/Ab3xK9
Python (requests)
import requests

res = requests.post(
    "https://ilync.dev/api/urls",
    json={"url": "https://example.com/a/very/long/path"},
    headers={"Authorization": "Bearer ilk_your_key_here"},  # optional
    timeout=10,
)
res.raise_for_status()
print(res.json()["shortUrl"])  # → https://ilync.dev/Ab3xK9

3. Use the response

A successful call returns 201 Created with the short link. Persist shortUrl (or shortCode) and hand it to your users — visiting it issues a 307 redirect to the original destination.

response — 201 Created
{
  "shortCode": "Ab3xK9",
  "shortUrl": "https://ilync.dev/Ab3xK9",
  "originalUrl": "https://example.com/a/very/long/path",
  "expiresAt": null,
  "createdAt": "2026-07-11T21:50:00.000Z",
  "isPrivate": false,
  "ownerId": null
}

That's the whole loop. From here, see Create a link for every request field, Authentication for keys, and Rate limits to size your usage.

Using the web UI

  1. Paste a long URL into the form on the home page.
  2. Optionally pick an expiration from the dropdown.
  3. Submit — the short link appears with a one-click Copy button.
  4. The Recently shortened list shows recent public links and their click counts; open a link's stats page at /{code}/stats.

Links created while signed out are public and appear in the landing-page feed. Links you create while signed inare unlisted — hidden from the public feed and tracked in your account's My links dashboard instead (they stay fully redirectable). Expired links are excluded from the public feed automatically.

Accounts & the dashboard

Accounts support Google and email/password sign-in. Visit /account to sign in or create one. Signing in is required to save links and to mint API keys.

Dashboard areaWhat it does
ProfileAvatar, editable display name, sign-in method, and a copyable user id.
StatsTotal links, active links, and links expiring in the next 7 days.
My linksEvery link you created while signed in — open, copy, view stats, or remove (removing only stops tracking; the short link keeps working).
Developer APICreate, list, and revoke API keys. This is the easiest way to manage keys (see API keys below).

Your saved links and profile are private to your account — only you can read or modify them.

Core concepts

ConceptSummary
Short codeA short, unique code (e.g. Ab3xK9) generated for each link — collision-free and non-sequential.
AccountA signed-in user. Required to save links to a dashboard and to mint API keys.
Public linkAnyone with the code is redirected, and it may appear in the public feed. The default for anonymous shortening.
Unlisted linkRedirectable by anyone with the code, but hidden from the public feed. Links created while signed in are unlisted.
Private linkOnly the owner or granted users may follow it; everyone else gets 401. Requires an API key to create.
API keyAn opaque token (ilk_…) that authenticates requests, raises your rate limit, and owns the links it creates. Minted from your account and tied to it.
User idEvery API key maps to a numeric userId, used for ownership checks and access grants.

Create a short link

POST/api/urlsAuth optional
FieldTypeRequiredNotes
urlstringyesWith or without a scheme (defaults to https://). http/https only, must have a dotted domain.
expiresAtstring | numbernoISO 8601 string or epoch ms. Must be in the future.
privatebooleannotrue creates a private link. Requires an API key.
listedbooleannoDefaults to true. Set false to keep the link out of the public feed (the signed-in web form does this automatically). Does not affect redirects.
request — anonymous, public link
curl -X POST https://ilync.dev/api/urls \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://example.com/a-very-long-url"}'
response — 201 Created
{
  "shortCode": "Ab3xK9",
  "shortUrl": "https://ilync.dev/Ab3xK9",
  "originalUrl": "https://example.com/a-very-long-url",
  "expiresAt": null,
  "createdAt": "2026-07-11T17:38:46.646Z",
  "isPrivate": false,
  "ownerId": null
}
request — authenticated, with expiry + private
curl -X POST https://ilync.dev/api/urls \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer ilk_your_key_here' \
  -d '{"url":"example.com/secret","expiresAt":"2026-12-31T23:59:59Z","private":true}'
201created400invalid URL/JSON/expiry401invalid key / private without key429rate limited500server error

Follow a short link (redirect)

GET/{code}Private only

Returns 307 Temporary Redirect with a Locationheader pointing to the original URL. For private links, send the owner's or a granted user's key.

curl -i https://ilync.dev/Ab3xK9 \
  -H 'Authorization: Bearer ilk_your_key_here'
307redirect404unknown code410expired401private, unauthorized

Delete a short link

DELETE/api/urls/{code}Owner
curl -X DELETE https://ilync.dev/api/urls/Ab3xK9 \
  -H 'Authorization: Bearer ilk_your_key_here'
204deleted401missing/invalid key403not the owner404unknown code

Grant access to a private link

POST/api/urls/{code}/accessOwner

Grants another user (by their userId) permission to follow a private link.

curl -X POST https://ilync.dev/api/urls/Ab3xK9/access \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer ilk_owner_key_here' \
  -d '{"userId":2}'
200granted400bad userId401missing/invalid key403not the owner404unknown code

Link analytics

GET/api/analytics/{code}Auth none

Returns click totals and breakdowns. Recording happens off the redirect hot path, so it never slows a redirect. A human-friendly page also lives at /{code}/stats.

curl https://ilync.dev/api/analytics/Ab3xK9
response — 200
{
  "shortCode": "Ab3xK9",
  "originalUrl": "https://example.com/…",
  "clicks": 4,
  "byPlatform": [
    { "platform": "iOS", "count": 1 },
    { "platform": "Windows", "count": 1 }
  ],
  "recent": [
    { "createdAt": "…", "referrer": "https://twitter.com/", "platform": "iOS" }
  ]
}
200ok404unknown code

Mint an API key

POST/api/keysAccount

You must have an account. Create a key from the account dashboard (easiest), or call the endpoint directly with your account ID token as a bearer token. The plaintext key is returned once (only its hash is stored) plus your userId.

curl -X POST https://ilync.dev/api/keys \
  -H 'Authorization: Bearer <YOUR_ID_TOKEN>' \
  -H 'Content-Type: application/json' \
  -d '{"label":"my-app"}'
response — 201
{ "apiKey": "ilk_6I2kaePfLIiEUUvVHHYMaBDzPre4npf4", "label": "my-app", "userId": 1 }

List your keys with GET /api/keys and revoke one with DELETE /api/keys/{id} (same bearer token).

Clean up expired links

POST/api/cleanupSecret / cron

Actively deletes every expired link (expired links are also removed lazily when someone tries to follow them, and are hidden from the public feed immediately). Pass CLEANUP_SECRETas a bearer token when set; when unset, it's reachable only outside production. Trigger it on a schedule.

curl -X POST https://ilync.dev/api/cleanup \
  -H 'Authorization: Bearer <CLEANUP_SECRET>'

Authentication & API keys

  • Sign in first. Minting keys requires an account — create one from the account dashboard, then generate keys there.
  • Send a key using either Authorization: Bearer ilk_… or X-API-Key: ilk_….
  • A valid key raises your rate limit, marks you as the owner of links you create, and enables private links.
  • Keys are stored only as SHA-256 hashes — the plaintext is shown once at creation, so save it.

Rate limits

Applied to POST /api/urls. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset; a 429 also includes Retry-After.

CallerLimitWindow
Anonymous (per IP)10 requests60 seconds
Authenticated (per key)100 requests60 seconds

Private URLs & access control

  1. Owner signs in and mints a key → gets apiKey and userId (say 1).
  2. Owner creates a link with "private": true using their key.
  3. Following the link works only with the owner's key; anyone else gets 401.
  4. The other user signs in and mints their own key to obtain their userId (say 2).
  5. Owner grants access: POST /api/urls/{code}/access with { "userId": 2 }.
  6. User 2 can now follow the link with their key.

Because access is enforced via an API-key header, private links are API-oriented — not a click-through-in-a-browser flow unless the client sends the key.

Expiration

  • Set expiresAt on creation as an ISO 8601 string or epoch milliseconds. It must be in the future.
  • Expired links return 410 Gone and are removed on access (passive cleanup).
  • Run POST /api/cleanup on a schedule for active cleanup.

Errors

Errors use standard HTTP status codes and return a JSON body with a human-readable error message. Always check the status code before parsing a success response.

error response — 400 Bad Request
{ "error": "Invalid URL: must be a valid http(s) address." }
StatusMeaning
400Malformed request — bad URL, JSON, or expiry.
401Missing or invalid credentials.
403Authenticated, but not allowed (e.g. not the owner).
404Unknown short code.
410The link has expired.
429Rate limit exceeded — retry after the window resets.