Links API
Create, list, edit and delete LinkTrail smart links over the REST API: the link object, its routing fields, all-time totals and the QR code endpoint.
Every endpoint on this page needs Authorization: Bearer <accessToken> and X-Workspace-Id: <id> — see Authentication. Paths are relative to https://backend.linktrail.io/v1.
| Method | Path | What it does |
|---|---|---|
| GET | /links | List links, newest first (paginated) |
| GET | /links/totals | All-time link, click and install totals |
| POST | /links | Create a link (the slug is generated if you omit it) |
| GET | /links/:linkId | Load one link |
| PATCH | /links/:linkId | Edit a link |
| DELETE | /links/:linkId | Delete a link |
| GET | /links/:linkId/qr | A QR code image for the link's URL |
Reading needs any role; creating, editing and deleting need editor, admin or owner. GET /links/resolve is the public endpoint the SDKs use — see SDK Endpoints.
The link object
{ "id": 1, "slug": "summer-promo", "domainId": 1, "domainHost": "acme.linktrail.io",
"url": "https://acme.linktrail.io/summer-promo",
"campaignId": 1, "campaignName": "Summer Sale", "channelId": 1, "channelName": "Paid social",
"deepLinkPath": "/products/42", "iosAppId": 3, "androidAppId": 4,
"iosUrl": "https://apps.apple.com/app/id123",
"androidUrl": "https://play.google.com/store/apps/details?id=com.acme.shop",
"fallbackUrl": "https://acme.com", "iosInterstitial": true, "utm": { "utm_source": "instagram" },
"customData": { "promoCode": "SUMMER" }, "status": "active",
"clicks": 0, "installs": 0, "cvr": "—",
"createdAt": "2026-05-28T00:00:00Z", "updatedAt": "2026-06-01T00:00:00Z" }statusis one ofactive,scheduled,expiredorarchived. Filter the list with?status=active,expired(one value or several).iosUrlandandroidUrlare read-only: the server derives them from the apps you associate withiosAppId/androidAppId. Sendnullto clear an association.iosInterstitial(defaulttrue) sends iOS visitors through the one-tap page that stages the click token for a deterministic deferred match;falseredirects straight to the App Store, and iOS attribution then falls back to IP-and-platform matching — only if that matching is switched on, which it is not by default.cvris computed by the server. Single-link responses also carryiosAppNameandandroidAppName.
Create a link
{ "domainId": 1, "slug": "summer-promo", "campaignId": 1, "channelId": 1,
"deepLinkPath": "/products/42", "iosAppId": 3, "androidAppId": 4,
"fallbackUrl": "https://acme.com", "iosInterstitial": true, "utm": { "utm_source": "instagram" },
"customData": { "promoCode": "SUMMER" } }A slug is letters, numbers, hyphens and underscores, unique per domain, and case-sensitive. Choosing one is a paid feature — Starter, Growth and Scale; on Free a request with slug answers 402. Leave it out on any plan and the server generates seven base58 characters. Creating a link past the plan's link limit also answers 402 (Free 100, Starter 1,000; Growth and Scale have no cap). An app id that is unknown, in another workspace or for the wrong platform answers 400.
PATCH /links/:linkId takes any subset of the same fields — slug and domainId included. Changing either changes the link's public URL: the old URL stops redirecting straight away, so anywhere it was already shared, printed or put in an ad breaks. (The dashboard shows both as read-only for that reason.)
Totals and QR codes
{ "links": 137, "clicks": 7421330, "installs": 912004,
"byStatus": {
"active": { "links": 112, "clicks": 6100230, "installs": 801220 },
"scheduled": { "links": 0, "clicks": 0, "installs": 0 },
"expired": { "links": 8, "clicks": 1201100, "installs": 99000 },
"archived": { "links": 17, "clicks": 120000, "installs": 11784 } } }GET /links/:linkId/qr?format=svg|png&size=512 returns the image bytes (image/svg+xml or image/png), 64 to 2048 pixels.