Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.linkutm.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Short links resolve at the root of the linkutm host, not under /api/v1. A short link looks like:
https://api.linkutm.com/<shortCode>
When a custom domain is in use, the same paths resolve on that domain instead. These endpoints are public. No Authorization header, no x-workspace-id header, no API key. They are the visitor-facing side of the product, separate from the authenticated API.
PathMethodPurpose
/:shortCodeGETResolve a short link and redirect the visitor
/qr/:shortCodeGETResolve a short link opened from its QR code
/:shortCodePOSTSubmit a password for a password-protected link
/GETBare-domain redirect to a domain’s configured default
GET /:shortCode
Looks up the link by its short code and, if it passes the checks below, issues an HTTP 302 redirect to the destination.

Example

curl -i https://api.linkutm.com/q2-launch
HTTP/1.1 302 Found
Location: https://example.com/q2-launch?utm_source=google&utm_medium=cpc&utm_campaign=q2_launch

Resolution order

1

Look up the short code

If no link exists with that short code, the response is 404 Not Found.
2

Check expiry

If expiresAt is set and is in the past, the response is 410 Gone with the message Link has expired. See the expiry note below.
3

Check archived state

If the link is archived, the response is 404 with the message Link not found.
4

Check password protection

If the link has a password and the visitor has not already verified it, an HTML password page is returned with status 200. See Password protection.
5

Count the click

If the visitor’s user agent looks like a real browser, the click is recorded and the link’s click counter is incremented. Bot and preview-crawler traffic is excluded - see Click counting.
6

Route by device

If the OS is detected as iOS and iosUrl is set, the visitor is redirected there. If the OS is Android and androidUrl is set, the visitor is redirected there. See Device deep linking.
7

Build the destination and redirect

The destination URL is built from the link’s url plus its UTM parameters. If the link has tracking pixels, a pixel-firing HTML page is returned instead of a bare redirect. See Pixel firing page. Otherwise a 302 to the destination is sent.

Destination URL

The redirect target is the link’s url with UTM query parameters appended:
  • utm_source, utm_medium, utm_campaign, utm_term, utm_content are added for whichever of those fields are set on the link.
  • Each key of customUtmParams is added with a utm_ prefix. {"audience": "lookalike_3"} becomes utm_audience=lookalike_3.

QR redirect

GET /qr/:shortCode
Identical resolution to GET /:shortCode, but the recorded click is flagged as a QR-code scan so it shows separately in analytics. The same flagging happens on GET /:shortCode when the request carries ?via=qr:
GET /:shortCode?via=qr
QR codes generated by linkutm point at /qr/:shortCode. The ?via=qr query parameter is an equivalent way to mark a scan when you cannot use the /qr/ path.

Password protection

When a link has a password set, the redirect does not happen until the visitor proves the password. GET /:shortCode on a protected link returns an HTML password page with status 200 (not a redirect, not an error) whenever the visitor lacks a valid verification cookie.

Submitting the password

POST /:shortCode
The password page submits a form back to this endpoint.
password
string
The password to check against the link.
curl -i -X POST https://api.linkutm.com/q2-launch \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "password=hunter2"
Behavior:
  • If the link has no password, this endpoint redirects straight to the destination with 302.
  • If the submitted password is wrong, the password page is re-rendered with status 200 and an Incorrect password. Please try again. message.
  • If the password is correct, a verification cookie named lnk_pw_<linkId> is set (httpOnly, sameSite=strict, scoped to /<shortCode>, one-hour lifetime), the click is counted, device routing is applied, and the visitor is redirected with 302 to the destination.
After a successful POST, subsequent GET /:shortCode requests that present the matching lnk_pw_<linkId> cookie skip the password page and redirect immediately. The cookie expires after one hour, after which the password is requested again.
A wrong password and a missing link both surface to the visitor as a 200 HTML page or a 404. The endpoint never reveals whether a short code exists when answering a failed password attempt - any lookup failure is returned as 404 Link not found.

Device deep linking

The redirect parses the visitor’s user agent to detect the operating system:
  • OS detected as iOS and the link has iosUrl set: the visitor is 302-redirected to iosUrl.
  • OS detected as Android and the link has androidUrl set: the visitor is 302-redirected to androidUrl.
  • Otherwise: the visitor goes to the standard UTM-built destination.
Device routing is applied on GET /:shortCode, GET /qr/:shortCode, and after a successful password POST. If the matching device URL is empty, the standard destination is used.
Device URLs are used verbatim. UTM parameters are not appended to iosUrl or androidUrl - only the standard url destination gets UTM query parameters.

Pixel firing page

If a link has one or more enabled tracking pixels, the redirect does not send a bare 302. Instead it returns a small HTML page that:
  1. Loads the pixel scripts for each attached pixel (Facebook, GA4, GTM, Twitter, LinkedIn, TikTok, Pinterest, Snapchat).
  2. Fires a page-view event on each.
  3. Redirects to the real destination after roughly 300 ms via setTimeout, with a 1 second meta refresh as a fallback.
The page is served with status 200 and Cache-Control: no-store. Visitors see a brief “Redirecting…” screen. Links with no pixels skip this page and get a direct 302.

Click counting

A click is recorded and the link counter incremented only when the visitor’s user agent looks like a genuine browser. The following traffic is excluded from counts:
  • Link-preview crawlers - Slack, Facebook, Twitter, LinkedIn, Discord, Telegram, Pinterest, WhatsApp, Embedly, iframely, Microsoft Teams, and similar.
  • HTTP client libraries and tools - curl, wget, python-requests, axios, node-fetch, okhttp, Postman, Insomnia, HTTPie, and similar.
  • Uptime and monitoring services - Pingdom, StatusCake, UptimeRobot, Site24x7, Better Stack.
  • Common SEO and scanning bots - AhrefsBot, SemrushBot, DotBot, MJ12bot, PetalBot, Applebot.
  • Headless browsers - HeadlessChrome, headless Edge, headless Firefox.
Excluded traffic is still redirected normally - it just does not count toward analytics or the click total. Click tracking and counter increments run asynchronously and never delay the redirect.
Because curl is filtered out, the curl examples on this page redirect correctly but do not register as clicks. Use a real browser to see a click recorded.

Bare-domain redirect

GET /
A request to the root of a linkutm domain with no short code is handled by the domain’s configuration:
  • If the domain has a defaultRedirect set and its status is active, the visitor is 302-redirected there.
  • Otherwise the response is 404 Page not found.
This lets a custom short domain forward its bare hostname (for example go.acme.com with no path) to a marketing site, while still serving short links on every other path.

Expiry and archived

StateResponseNotes
expiresAt in the past410 Link has expiredExpired links stop resolving.
archived: true404 Link not foundArchived links do not resolve.
Short code unknown404 Link not found

Errors

CodeWhen
200Password page shown, or pixel-firing page served - this is not an error, the body is HTML
302Normal redirect to the destination, device URL, or bare-domain default
404Short code not found, link archived, or bare domain with no configured default
410Link is past its expiresAt and no longer resolves