Features · Developers

urlf.ly API documentation

Create, list, update, and delete your short links and read their click stats from your own scripts, over a small JSON API.

The API is part of the Premium plan.

Shorten a link JOIN NOW

Overview

Authentication

  1. Sign in and open API keys from your dashboard.
  2. Name the key and press Create key. The full key, starting uf_, is shown once only. Store it somewhere safe.
  3. Send it with every request, either as a Bearer token or in an X-Api-Key header.
curl -H "Authorization: Bearer uf_YOUR_API_KEY" https://urlf.ly/api/v1/links
curl -H "X-Api-Key: uf_YOUR_API_KEY" https://urlf.ly/api/v1/links

You can hold up to 20 active keys and revoke any of them from the same page. Only a hash of each key is stored. A missing, wrong, or revoked key gets 401. After 30 failed attempts from one IP address within 10 minutes, further attempts get 429 until the window passes.

Rate limits

Each key can make 1,000 requests per hour. Once a key is accepted and the API is on its owner’s plan, responses carry X-RateLimit-Limit: 1000. Past the limit you get 429 with a Retry-After header giving the seconds to wait.

Request bodies are limited to 64 KB.

Endpoints

Method and pathWhat it does
GET /linksList your links, newest first
POST /linksCreate a link
GET /links/{ref}Get one link
PATCH /links/{ref}Change a link
DELETE /links/{ref}Delete a link
GET /links/{ref}/statsClick stats for a link

Paths are relative to the base URL. {ref} is the link’s numeric id or its short code. A number is tried as an id first, then as a code. A link you do not own returns 404.

{
  "id": 1234,
  "code": "launch",
  "short_url": "https://urlf.ly/launch",
  "destination": "https://example.com/blog/launch-day",
  "title": "Launch post",
  "notes": null,
  "status": "active",
  "clicks": 0,
  "created_at": "2026-11-09 18:00:00",
  "updated_at": "2026-11-09 18:00:00",
  "expires_at": null,
  "encrypted": false
}

status is active or disabled. short_url uses your branded domain when the link is on one. expires_at is null for a link that does not expire.

List links

GET /links?page=1&per_page=20. page starts at 1. per_page defaults to 20; the most is 100.

{
  "items": [ { "id": 1234, "code": "launch", "...": "..." } ],
  "page": 1,
  "per_page": 20,
  "total": 1
}

Create a link

curl -X POST https://urlf.ly/api/v1/links \
  -H "Authorization: Bearer uf_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/blog/launch-day", "title": "Launch post"}'

Returns 201:

{
  "id": 1234,
  "code": "aB3xY9",
  "short_url": "https://urlf.ly/aB3xY9",
  "destination": "https://example.com/blog/launch-day",
  "created_at": "2026-11-09 18:00:00"
}

If you already have an active link to exactly the same URL, that link is returned instead of a new one, even when you send an alias.

Fields for create and update

FieldMeaning
urlThe destination, an http or https address. Required when creating.
aliasYour own short code: 3 to 32 letters, numbers, _ or -. Taken codes return 409, reserved words 422. Without it a random code is made. Needs the Premium plan. On update, a different alias renames the link and the old code stops working (Premium plan).
titleA label for the link, up to 200 characters.
notesPrivate notes, up to 2,000 characters.
expiryA number of days, or a future date such as 2026-12-31. 0 means never. When creating without it, the link does not expire. On update, leaving it out keeps the current expiry.
tagsA list of strings, or one comma-separated string. Needs the Premium plan; ignored otherwise.
max_clicksStop the link after this many counted clicks; 0 means no limit. Needs the Premium plan; ignored otherwise.
passwordAsk visitors for this password, 4 to 72 characters. Needs the Premium plan; ignored otherwise. An empty value leaves the current password alone; remove a password from the link’s Edit page.

Other options, such as country routing or cloaking, are set on the dashboard; the API does not change them.

Get a link

curl -H "Authorization: Bearer uf_YOUR_API_KEY" https://urlf.ly/api/v1/links/launch

Returns 200 with the link object.

Update a link

Send only the fields you want to change. Fields you leave out keep their current value. null clears title, notes, or tags.

curl -X PATCH https://urlf.ly/api/v1/links/launch \
  -H "Authorization: Bearer uf_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/blog/launch-day-updated"}'

Returns 200 with the updated link object.

Delete a link

curl -X DELETE -H "Authorization: Bearer uf_YOUR_API_KEY" https://urlf.ly/api/v1/links/launch

Returns 204 with no body. The short link stops working.

Link stats

curl -H "Authorization: Bearer uf_YOUR_API_KEY" https://urlf.ly/api/v1/links/launch/stats
{
  "link_id": 1234,
  "code": "launch",
  "clicks_total": 2,
  "unique_visitors": 2,
  "qr_scans": 1,
  "last_7_days": [
    { "day": "2026-11-03", "clicks": 0 },
    "... one entry per day ...",
    { "day": "2026-11-09", "clicks": 2 }
  ],
  "top_countries": [ { "code": "US", "label": "United States", "clicks": 2 } ],
  "top_referrers": [ { "label": "news.example.org", "clicks": 1 } ]
}

The numbers above are an example. clicks_total, unique_visitors, and qr_scans cover the life of the link. last_7_days has one entry per UTC day, today included. top_countries (up to 15) and top_referrers (up to 10) cover the same 7 days. Known bots are not counted.

Errors

Errors return JSON with a single error message, for example {"error": "url is required"}.

StatusWhen
400The body is not valid JSON.
401Missing, wrong, or revoked key. Sent with WWW-Authenticate: Bearer.
403The API is not on your plan, or is switched off.
404Unknown path, or no link of yours with that id or code.
405Wrong method for the path. The Allow header lists the right ones.
409The alias is already taken.
413The body is larger than 64 KB.
422A field is missing or invalid, such as a bad URL or alias.
429Rate limit reached, or too many failed key attempts. See Retry-After.
500Something went wrong on our side.

Webhooks

To be told when a link is created, changed, deleted, or clicked, add a webhook from your dashboard instead of polling the API. Webhooks: Premium plan.

Frequently asked questions

Who can use the urlf.ly API?

Members on the Premium plan can create API keys from the dashboard.

Is there a rate limit?

Yes. Each key can make 1,000 requests per hour. Past that the API returns 429 with a Retry-After header.

Can I use the API from a browser?

It is meant for servers and scripts. Keep your key secret: anyone with the key can manage your links.

What happens to an option my plan does not include?

Fields such as password, tags, and max_clicks are ignored when your plan does not include that feature. The rest of the request still succeeds.

Ready to create your link?

Shorten a link in seconds, then add the options you need.

Shorten a link JOIN NOW