Tracked links
A tracked link is a short WhatSetter address (https://app.whatsetter.com/l/insta-bio) that opens a WhatsApp conversation with one of your agents and records the click. The API exposes your links and their stats read-only; you create and edit them in the dashboard.
Endpoints
Section titled “Endpoints”| Method | Path | Scope |
|---|---|---|
| GET | /links |
links:read |
| GET | /links/{id} |
links:read |
List links
Section titled “List links”curl "https://app.whatsetter.com/api/v1/links?status=active&limit=25" \ -H "Authorization: Bearer ws_live_…"const res = await fetch('https://app.whatsetter.com/api/v1/links?status=active&limit=25', { headers: { Authorization: 'Bearer ws_live_…' },});const { data: links, pagination } = await res.json();import requests
r = requests.get( "https://app.whatsetter.com/api/v1/links", params={"status": "active", "limit": 25}, headers={"Authorization": "Bearer ws_live_…"},)links = r.json()["data"]{ "data": [ { "id": "66f1a2b3c4d5e6f7a8b9c0f1", "slug": "insta-bio", "name": "Instagram bio", "url": "https://app.whatsetter.com/l/insta-bio", "campaign_id": "acme-france-1-ab12", "status": "active", "channel": "auto", "clicks": 128, "last_click_at": "2026-09-18T10:00:00.000Z", "created_at": "2026-09-01T08:00:00.000Z" } ], "pagination": { "has_more": false, "next_cursor": null }}| Parameter | What it does |
|---|---|
campaign_id |
The campaign’s slug or its id. |
status |
active or inactive. |
limit, cursor |
Pagination. |
| Field | Meaning |
|---|---|
url |
The address to share. |
campaign_id |
The campaign (and so the WhatsApp number) the link opens. |
channel |
auto when the platform is read on each click, or a forced platform. |
clicks |
Total clicks since creation. Preview robots and crawlers are not counted. |
Get one link with its 30-day stats
Section titled “Get one link with its 30-day stats”curl "https://app.whatsetter.com/api/v1/links/66f1a2b3c4d5e6f7a8b9c0f1" \ -H "Authorization: Bearer ws_live_…"const res = await fetch('https://app.whatsetter.com/api/v1/links/66f1a2b3c4d5e6f7a8b9c0f1', { headers: { Authorization: 'Bearer ws_live_…' },});const { data: link } = await res.json();import requests
r = requests.get( "https://app.whatsetter.com/api/v1/links/66f1a2b3c4d5e6f7a8b9c0f1", headers={"Authorization": "Bearer ws_live_…"},)link = r.json()["data"]{ "data": { "id": "66f1a2b3c4d5e6f7a8b9c0f1", "slug": "insta-bio", "name": "Instagram bio", "url": "https://app.whatsetter.com/l/insta-bio", "campaign_id": "acme-france-1-ab12", "status": "active", "channel": "auto", "clicks": 128, "last_click_at": "2026-09-18T10:00:00.000Z", "created_at": "2026-09-01T08:00:00.000Z", "stats_30d": { "clicks": 128, "by_channel": { "instagram": 90, "tiktok": 30, "direct": 8 }, "leads": 41, "qualified": 12 } }}stats_30d holds the same numbers as the link’s drawer in the dashboard: clicks over the last 30 days, split by the platform read on each click, plus the conversations the link brought and how many of them were qualified.
How attribution works
Section titled “How attribution works”The platform is read at click time, never guessed from the message: the app the link was opened from (Instagram, TikTok, LinkedIn…), the referrer, or the variant of the link you shared (?c=qr, ?c=email, ?c=sms for silent supports), otherwise direct. When the person then writes to the number, WhatSetter looks at the clicks on that number’s links in the last 45 minutes. One click, or clicks from a single platform, gives a certain attribution; several platforms in the window gives the most recent click from the person’s country, marked probable. A message carrying a Meta ad signal is attributed to the ad, certain, without any link. No click at all means the person wrote spontaneously: inbound.
Each lead then carries source (the platform), tracked_link_id (this link’s id) and source_confidence (certain or probable). Filter them with GET /leads?tracked_link_id= or ?source=instagram.
Errors you will meet
Section titled “Errors you will meet”| HTTP | code |
When |
|---|---|---|
| 401 | missing_api_key, invalid_api_key |
Key absent, unknown or revoked. |
| 403 | insufficient_scope |
The key lacks links:read. |
| 404 | not_found |
Unknown link, or a link of another workspace. |
| 422 | validation_error |
Unknown status, invalid cursor. |
| 429 | rate_limited |
Too many requests this minute. Honor Retry-After. |

