{"components":{"responses":{},"schemas":{"ApiError":{"description":"Response schema for API error","example":{"error":"Something went wrong"},"properties":{"error":{"type":"string"}},"title":"ApiError","type":"object"},"ClickResponse":{"description":"Response schema for Click","properties":{"t":{"description":"Start of the bucket. `YYYY-MM-DD` when `frequency=day`; `YYYY-MM-DDTHH:MM:SS` when `frequency=hour`.","example":"2026-06-01","type":"string"},"y":{"description":"Click count for the bucket.","nullable":true,"type":"integer"}},"title":"ClickResponse","type":"object"},"ClicksResponse":{"description":"Response schema for Clicks","example":{"traffic":[{"t":"2026-06-01","y":12},{"t":"2026-06-02","y":8},{"t":"2026-06-03","y":21}]},"properties":{"traffic":{"items":{"description":"Response schema for Click","properties":{"t":{"description":"Start of the bucket. `YYYY-MM-DD` when `frequency=day`; `YYYY-MM-DDTHH:MM:SS` when `frequency=hour`.","example":"2026-06-01","type":"string"},"y":{"description":"Click count for the bucket.","nullable":true,"type":"integer"}},"title":"ClickResponse","type":"object"},"type":"array"}},"title":"ClicksResponse","type":"object"},"Conversion":{"properties":{"amount_cents":{"example":4999,"nullable":true,"type":"integer"},"click_id":{"description":"The click the conversion is attributed to.","example":"01KYPGEEPJSPR3S564QRBDGA1W","type":"string"},"country":{"example":"US","nullable":true,"type":"string"},"currency":{"example":"USD","nullable":true,"type":"string"},"event_id":{"example":"shopify-1234","nullable":true,"type":"string"},"event_name":{"example":"purchase","type":"string"},"event_type":{"example":"sale","type":"string"},"external_id":{"example":"customer-42","nullable":true,"type":"string"},"id":{"description":"ULID. Sorts chronologically, so ids are ordered by creation.","example":"01KYPH20SEJY4HQSCPMWW60QE0","type":"string"},"inserted_at":{"description":"When Linkly stored it. UTC, ISO 8601 without an offset (`YYYY-MM-DDTHH:MM:SS`), unlike `occurred_at`.","example":"2026-07-29T10:30:01","type":"string"},"ip_source":{"description":"Whose address was recorded. `server` means the connecting address belonged to your backend or a platform relay, so it is excluded from geographic reporting. The address itself is never returned.","enum":["visitor","server","unknown"],"example":"visitor","type":"string"},"link_id":{"description":"The link the conversion is attributed to.","example":41657524,"type":"integer"},"metadata":{"nullable":true,"type":"object"},"occurred_at":{"description":"When the conversion happened, UTC with offset.","example":"2026-07-29T10:30:00.123456Z","format":"date-time","type":"string"},"source":{"description":"Which integration reported it.","example":"api","type":"string"}},"required":["id","link_id","click_id","event_type","event_name","source","occurred_at","inserted_at"],"title":"Conversion","type":"object"},"ConversionCreateRequest":{"description":"A conversion to record","properties":{"amount_cents":{"description":"Value in the smallest currency unit. May be negative to record a refund or chargeback, which nets against earlier revenue.","example":4999,"type":"integer"},"country":{"description":"Two-letter country code for the conversion. Inferred for browser-side calls; supply it explicitly from a server-side integration, where the connecting address is your own infrastructure rather than the customer's.","example":"US","type":"string"},"currency":{"description":"ISO 4217 currency code. Defaults to USD.","example":"USD","type":"string"},"event_id":{"description":"Your identifier for this event. Used as an idempotency key — reporting the same value twice will not create a second conversion. Applies to any event type, not just purchases.","example":"shopify-1234","type":"string"},"event_name":{"description":"What happened, e.g. `purchase`, `signup`, `trial_started`","example":"purchase","type":"string"},"event_type":{"description":"Coarse type driving the funnel. `lead` establishes customer identity, `sale` records revenue. Defaults to `custom`.","enum":["lead","sale","custom"],"example":"sale","type":"string"},"external_id":{"description":"Your identifier for the customer. Send it on every event: it is what links a later server-side sale back to the click that produced the signup.","example":"customer-42","type":"string"},"linkly_cid":{"description":"The attribution token captured from the landing page URL. Omit if unavailable — the conversion is then recorded without a link attribution.","example":"2on1Y.01KYPGEEPJSPR3S564QRBDGA1W","type":"string"},"metadata":{"description":"Arbitrary JSON, up to 10,000 bytes encoded.","example":{"sku":"ABC-123"},"type":"object"},"occurred_at":{"description":"When the conversion happened. Defaults to now.","example":"2026-07-29T10:30:00Z","format":"date-time","type":"string"},"visitor_ip":{"description":"The end customer's IP, when your server has it. Omit unless you do — for server-side calls Linkly otherwise records the connecting address as your server, not the customer, and excludes it from geographic reporting. Sending this asserts you have a lawful basis to share it. Never returned by the API.","example":"203.0.113.42","type":"string"}},"required":["event_name"],"title":"ConversionCreateRequest","type":"object"},"ConversionList":{"properties":{"conversions":{"items":{"properties":{"amount_cents":{"example":4999,"nullable":true,"type":"integer"},"click_id":{"description":"The click the conversion is attributed to.","example":"01KYPGEEPJSPR3S564QRBDGA1W","type":"string"},"country":{"example":"US","nullable":true,"type":"string"},"currency":{"example":"USD","nullable":true,"type":"string"},"event_id":{"example":"shopify-1234","nullable":true,"type":"string"},"event_name":{"example":"purchase","type":"string"},"event_type":{"example":"sale","type":"string"},"external_id":{"example":"customer-42","nullable":true,"type":"string"},"id":{"description":"ULID. Sorts chronologically, so ids are ordered by creation.","example":"01KYPH20SEJY4HQSCPMWW60QE0","type":"string"},"inserted_at":{"description":"When Linkly stored it. UTC, ISO 8601 without an offset (`YYYY-MM-DDTHH:MM:SS`), unlike `occurred_at`.","example":"2026-07-29T10:30:01","type":"string"},"ip_source":{"description":"Whose address was recorded. `server` means the connecting address belonged to your backend or a platform relay, so it is excluded from geographic reporting. The address itself is never returned.","enum":["visitor","server","unknown"],"example":"visitor","type":"string"},"link_id":{"description":"The link the conversion is attributed to.","example":41657524,"type":"integer"},"metadata":{"nullable":true,"type":"object"},"occurred_at":{"description":"When the conversion happened, UTC with offset.","example":"2026-07-29T10:30:00.123456Z","format":"date-time","type":"string"},"source":{"description":"Which integration reported it.","example":"api","type":"string"}},"required":["id","link_id","click_id","event_type","event_name","source","occurred_at","inserted_at"],"title":"Conversion","type":"object"},"type":"array"},"has_more":{"description":"True when more conversions follow this page. When paging with `since` or `after`, request the next page with `after` set to the last `id` here.","example":false,"type":"boolean"}},"required":["conversions","has_more"],"title":"ConversionList","type":"object"},"ConversionUnattributed":{"description":"The conversion could not be attributed to a link and was discarded. Not an error: do not retry.","properties":{"attributed":{"enum":[false],"example":false,"type":"boolean"},"message":{"example":"Conversion could not be attributed to a link and was not recorded. Check that linkly_cid is being captured and sent.","type":"string"}},"required":["attributed","message"],"title":"ConversionUnattributed","type":"object"},"CountersResponse":{"description":"Response schema for Counters","example":{"total":215,"values":[{"count":120,"value":"US"},{"count":64,"value":"GB"},{"count":31,"value":"DE"}]},"properties":{"total":{"description":"Total clicks across all groups, including any not returned in `values`. When the result is truncated this is greater than the sum of `count` in `values`, so `count / total` still gives an accurate percentage.","type":"integer"},"values":{"description":"Grouped counts, ordered by count descending. Truncated to the top 10,000 values; if the dimension has more distinct values than that, the rest are not returned.","items":{"properties":{"count":{"type":"integer"},"key":{"description":"Only present for `counter=top_params`: the query-parameter name that `value` was seen on.","type":"string"},"value":{"description":"The grouped value. A string for every counter except `link_id`, which returns the full Link object; null when the dimension was not recorded for those clicks.","nullable":true,"oneOf":[{"type":"string"},{"$ref":"#/components/schemas/Link"}]}},"type":"object"},"maxItems":10000,"type":"array"}},"title":"CountersResponse","type":"object"},"CreateDomainRequest":{"properties":{"name":{"description":"Domain name (e.g., links.example.com)","type":"string"}},"required":["name"],"title":"CreateDomainRequest","type":"object"},"CreateOrUpdateLinkRequest":{"description":"Request body for creating or updating a link","properties":{"fb_pixel_id":{"description":"Facebook Pixel ID","nullable":true,"type":"string"},"tiktok_pixel_id":{"description":"TikTok Pixel ID","nullable":true,"type":"string"},"hide_referrer":{"description":"Hide referrer from destination","type":"boolean"},"expiry_datetime":{"description":"Link expiration date/time","format":"date-time","nullable":true,"type":"string"},"expiry_destination":{"description":"Redirect URL after expiry","nullable":true,"type":"string"},"rules":{"description":"Redirect rules","items":{"$ref":"#/components/schemas/Rule"},"type":"array"},"domain_id":{"description":"Domain ID (alternative to domain name)","type":"integer"},"cloaking":{"description":"Enable link cloaking","type":"boolean"},"linkify_words":{"description":"Words to linkify","nullable":true,"type":"string"},"sticky_rotator":{"description":"Rotator links only: send a returning visitor to the same destination as last time, remembered in a cookie for 30 days. Not available on privacy-mode links; turning privacy mode on switches it off.","type":"boolean"},"og_description":{"description":"Open Graph description","nullable":true,"type":"string"},"skip_social_crawler_tracking":{"description":"Skip tracking social media crawlers","type":"boolean"},"body_tags":{"description":"Custom HTML tags for body","nullable":true,"type":"string"},"og_title":{"description":"Open Graph title","nullable":true,"type":"string"},"note":{"description":"Private note about this link","nullable":true,"type":"string"},"name":{"description":"Nickname for the link","nullable":true,"type":"string"},"id":{"description":"Link ID (include to update existing link)","type":"integer"},"gtm_id":{"description":"Google Tag Manager ID","nullable":true,"type":"string"},"og_image":{"description":"Open Graph image URL","nullable":true,"type":"string"},"block_bots":{"description":"Block bot traffic","type":"boolean"},"utm_content":{"nullable":true,"type":"string"},"enabled":{"description":"Whether the link is active","type":"boolean"},"privacy_mode":{"description":"Record clicks without personal data (no IP, location, network, user agent, referrer or query parameters; click times kept to the hour). Turning it on also clears tracking pixels, custom scripts, conversion tracking, webhooks and click notifications on the link, and click webhooks stop firing for it. Paid plans only.","type":"boolean"},"url":{"description":"The destination URL","format":"uri","type":"string"},"replacements":{"description":"URL parameter replacements","nullable":true,"type":"string"},"qr_styles":{"description":"QR code styling options","nullable":true,"type":"object"},"webhooks":{"description":"Webhook URLs","items":{"type":"string"},"type":"array"},"expiry_clicks":{"description":"Expire link after this many clicks","nullable":true,"type":"integer"},"public_analytics":{"description":"Make analytics publicly accessible","type":"boolean"},"utm_source":{"nullable":true,"type":"string"},"slug":{"description":"Custom slug (must start with /)","nullable":true,"type":"string"},"domain":{"description":"Custom domain (without trailing /)","nullable":true,"type":"string"},"forward_params":{"description":"Forward query parameters to destination","type":"boolean"},"utm_medium":{"nullable":true,"type":"string"},"head_tags":{"description":"Custom HTML tags for head","nullable":true,"type":"string"},"ga4_tag_id":{"description":"Google Analytics 4 Tag ID","nullable":true,"type":"string"},"utm_term":{"nullable":true,"type":"string"},"utm_campaign":{"nullable":true,"type":"string"}},"required":["url"],"title":"CreateOrUpdateLinkRequest","type":"object"},"DeleteLinksRequest":{"description":"Delete body to delete links","properties":{"ids":{"items":{"type":"integer"},"type":"array"}},"title":"DeleteLinksRequest","type":"object"},"Domain":{"description":"Response schema for a domain","example":{"name":null,"workspace_id":42},"properties":{"name":{"nullable":true,"type":"string"},"workspace_id":{"nullable":true,"type":"integer"}},"title":"Domain","type":"object"},"DomainCreateRequest":{"description":"POST body for creating a Domain","example":{"name":"link.mydomain.com","workspace_id":33},"properties":{"name":{"description":"name","type":"string"},"workspace_id":{"description":"Workspace ID","type":"integer"}},"required":["workspace_id"],"title":"DomainCreateRequest","type":"object"},"DomainListItem":{"description":"A custom domain in a workspace.","properties":{"name":{"nullable":true,"type":"string"}},"title":"DomainListItem","type":"object"},"DomainListResponse":{"description":"List of custom domains configured for a workspace.","example":{"domains":[{"name":"go.yourcompany.com"},{"name":"links.example.com"}]},"properties":{"domains":{"items":{"description":"A custom domain in a workspace.","properties":{"name":{"nullable":true,"type":"string"}},"title":"DomainListItem","type":"object"},"type":"array"}},"title":"DomainListResponse","type":"object"},"GetLinkResponse":{"description":"Response schema for getting a single link","properties":{"base62_id":{"type":"string"},"clicks_count":{"description":"Lifetime click count for this link, including bot traffic","type":"integer"},"domain":{"nullable":true,"type":"object"},"domains":{"items":{"type":"object"},"type":"array"},"link":{"description":"A link with click statistics, as returned by workspace link endpoints.","properties":{"fb_pixel_id":{"nullable":true,"type":"string"},"human_clicks_total":{"description":"Lifetime clicks with no bot signal — the subset of `clicks_total` where neither a bot user-agent nor a verified-bot category was detected. Recorded from 2019 onward.","type":"integer"},"sparkline":{"description":"Daily human clicks over the last 30 days, oldest first.","items":{"type":"integer"},"type":"array"},"clicks_thirty_days":{"description":"Clicks in the last 30 days, including bot traffic.","type":"integer"},"tiktok_pixel_id":{"nullable":true,"type":"string"},"hide_referrer":{"nullable":true,"type":"boolean"},"rules":{"items":{"$ref":"#/components/schemas/Rule"},"nullable":true,"type":"array"},"cloaking":{"nullable":true,"type":"boolean"},"linkify_words":{"nullable":true,"type":"string"},"full_url":{"format":"uri","type":"string"},"clicks_today":{"description":"Clicks so far today (UTC), including bot traffic.","type":"integer"},"og_description":{"nullable":true,"type":"string"},"body_tags":{"nullable":true,"type":"string"},"og_title":{"nullable":true,"type":"string"},"note":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"id":{"nullable":true,"type":"integer"},"gtm_id":{"nullable":true,"type":"string"},"og_image":{"nullable":true,"type":"string"},"block_bots":{"nullable":true,"type":"boolean"},"clicks_total":{"description":"Lifetime clicks, including bot traffic.","type":"integer"},"human_clicks_thirty_days":{"description":"Clicks in the last 30 days with no bot signal — the subset of `clicks_thirty_days`.","type":"integer"},"utm_content":{"nullable":true,"type":"string"},"human_clicks_today":{"description":"Clicks so far today (UTC) with no bot signal.","type":"integer"},"enabled":{"nullable":true,"type":"boolean"},"url":{"format":"uri","type":"string"},"replacements":{"nullable":true,"type":"string"},"deleted":{"nullable":true,"type":"boolean"},"workspace_id":{"nullable":true,"type":"integer"},"public_analytics":{"nullable":true,"type":"boolean"},"utm_source":{"nullable":true,"type":"string"},"slug":{"nullable":true,"type":"string"},"domain":{"nullable":true,"type":"string"},"forward_params":{"nullable":true,"type":"boolean"},"utm_medium":{"nullable":true,"type":"string"},"head_tags":{"nullable":true,"type":"string"},"ga4_tag_id":{"nullable":true,"type":"string"},"utm_term":{"nullable":true,"type":"string"},"utm_campaign":{"nullable":true,"type":"string"},"human_clicks_previous_day":{"description":"Clicks yesterday (UTC) with no bot signal.","type":"integer"}},"title":"WorkspaceLink","type":"object"}},"title":"GetLinkResponse","type":"object"},"Link":{"description":"Response schema for a link","example":{"fb_pixel_id":null,"linkedin_partner_id":null,"microsoft_uet_tag_id":null,"reddit_pixel_id":null,"tiktok_pixel_id":null,"hide_referrer":false,"expiry_datetime":null,"expiry_destination":null,"rules":[],"twitter_pixel_id":null,"cloaking":false,"linkify_words":null,"full_url":"https://l.linklyhq.com/l/1uXyz","sticky_rotator":false,"og_description":null,"skip_social_crawler_tracking":false,"body_tags":null,"og_title":null,"note":null,"name":"Summer sale — newsletter","id":41657524,"gtm_id":null,"og_image":null,"block_bots":false,"snapchat_pixel_id":null,"utm_content":null,"enabled":true,"privacy_mode":false,"url":"https://www.example.com/summer-sale?ref=newsletter","replacements":null,"deleted":false,"qr_styles":null,"webhooks":[],"created_by_user_id":7,"expiry_clicks":null,"notify_slack":false,"notify_user_ids":[],"workspace_id":42,"public_analytics":false,"pinterest_tag_id":null,"password":null,"utm_source":"newsletter","slug":null,"domain":null,"forward_params":false,"utm_medium":"email","head_tags":null,"ga4_tag_id":null,"utm_term":null,"utm_campaign":"summer_sale"},"properties":{"fb_pixel_id":{"nullable":true,"type":"string"},"linkedin_partner_id":{"nullable":true,"type":"string"},"microsoft_uet_tag_id":{"nullable":true,"type":"string"},"reddit_pixel_id":{"nullable":true,"type":"string"},"tiktok_pixel_id":{"nullable":true,"type":"string"},"hide_referrer":{"nullable":true,"type":"boolean"},"expiry_datetime":{"nullable":true,"type":"string"},"expiry_destination":{"format":"uri","nullable":true,"type":"string"},"rules":{"items":{"$ref":"#/components/schemas/Rule"},"nullable":true,"type":"array"},"twitter_pixel_id":{"nullable":true,"type":"string"},"cloaking":{"nullable":true,"type":"boolean"},"linkify_words":{"nullable":true,"type":"string"},"full_url":{"format":"uri","type":"string"},"sticky_rotator":{"description":"Rotator links only: a visitor who has been sent to one of the rotator's destinations is sent to the same one again when they click the link again, remembered in a cookie for 30 days.","type":"boolean"},"og_description":{"nullable":true,"type":"string"},"skip_social_crawler_tracking":{"nullable":true,"type":"boolean"},"body_tags":{"nullable":true,"type":"string"},"og_title":{"nullable":true,"type":"string"},"note":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"id":{"type":"integer"},"gtm_id":{"nullable":true,"type":"string"},"og_image":{"nullable":true,"type":"string"},"block_bots":{"nullable":true,"type":"boolean"},"snapchat_pixel_id":{"nullable":true,"type":"string"},"utm_content":{"nullable":true,"type":"string"},"enabled":{"nullable":true,"type":"boolean"},"privacy_mode":{"description":"Privacy mode: clicks are counted, but no IP address, location, network, user agent, referrer or query parameters are stored, and click times are kept to the hour. Paid plans only.","type":"boolean"},"url":{"format":"uri","type":"string"},"replacements":{"nullable":true,"type":"string"},"deleted":{"nullable":true,"type":"boolean"},"qr_styles":{"nullable":true,"type":"object"},"webhooks":{"items":{"type":"string"},"nullable":true,"type":"array"},"created_by_user_id":{"nullable":true,"type":"integer"},"expiry_clicks":{"nullable":true,"type":"integer"},"notify_slack":{"nullable":true,"type":"boolean"},"notify_user_ids":{"items":{"type":"integer"},"nullable":true,"type":"array"},"workspace_id":{"type":"integer"},"public_analytics":{"nullable":true,"type":"boolean"},"pinterest_tag_id":{"nullable":true,"type":"string"},"password":{"nullable":true,"type":"string"},"utm_source":{"nullable":true,"type":"string"},"slug":{"nullable":true,"type":"string"},"domain":{"nullable":true,"type":"string"},"forward_params":{"nullable":true,"type":"boolean"},"utm_medium":{"nullable":true,"type":"string"},"head_tags":{"nullable":true,"type":"string"},"ga4_tag_id":{"nullable":true,"type":"string"},"utm_term":{"nullable":true,"type":"string"},"utm_campaign":{"nullable":true,"type":"string"}},"title":"Link","type":"object"},"LinkBulkRequest":{"description":"A JSON array of up to 1000 link objects to create or update.","items":{"description":"POST body for creating or updating an link","example":{"url":"www.somelink.com","workspace_id":33},"properties":{"fb_pixel_id":{"description":"fb_pixel_id","type":"string"},"tiktok_pixel_id":{"description":"tiktok_pixel_id","type":"string"},"hide_referrer":{"description":"hide_referrer","type":"boolean"},"expiry_datetime":{"description":"When the link expires (ISO 8601). After this time visitors are sent to `expiry_destination`. The year must be between 2000 and 2100.","example":"2026-12-31T23:59:59Z","format":"date-time","type":"string"},"expiry_destination":{"description":"Where visitors are sent once the link has expired (by date or by click count). Must start with `http`.","example":"https://example.com/expired","format":"uri","type":"string"},"rules":{"items":{"properties":{"matches":{"type":"string"},"percentage":{"type":"string"},"rule_url":{"type":"string"},"url":{"type":"string"},"what":{"type":"string"}},"type":"object"},"type":"array"},"cloaking":{"description":"cloaking","type":"boolean"},"linkify_words":{"description":"linkify_words","type":"string"},"og_description":{"description":"og_description","type":"string"},"body_tags":{"description":"body_tags","type":"string"},"spam":{"description":"spam","type":"boolean"},"og_title":{"description":"og_title","type":"string"},"note":{"description":"note","type":"string"},"name":{"description":"name","type":"string"},"id":{"description":"Link ID. Required to update an existing link","type":"integer"},"gtm_id":{"description":"gtm_id","type":"string"},"og_image":{"description":"og_image","type":"string"},"block_bots":{"description":"block_bots","type":"boolean"},"utm_content":{"description":"utm_content","type":"string"},"enabled":{"description":"enabled","type":"boolean"},"url":{"description":"URL. Required to create a new link.","example":"www.somelink.com","format":"uri","type":"string"},"replacements":{"description":"replacements","type":"string"},"deleted":{"description":"deleted","type":"boolean"},"expiry_clicks":{"description":"Expire the link after this many clicks; visitors are then sent to `expiry_destination`.","example":1000,"type":"integer"},"workspace_id":{"description":"Workspace ID","type":"integer"},"utm_source":{"description":"utm_source","type":"string"},"slug":{"description":"slug","type":"string"},"domain":{"description":"domain","type":"string"},"forward_params":{"description":"forward_params","type":"boolean"},"utm_medium":{"description":"utm_medium","type":"string"},"head_tags":{"description":"head_tags","type":"string"},"ga4_tag_id":{"description":"ga4_tag_id","type":"string"},"utm_term":{"description":"utm_term","type":"string"},"utm_campaign":{"description":"utm_campaign","type":"string"}},"title":"LinkCreateOrUpdateRequest","type":"object"},"maxItems":1000,"title":"LinkBulkRequest","type":"array"},"LinkBulkResult":{"description":"One result per submitted link, in request order.","items":{"properties":{"error":{"description":"Error detail (present when status is error)","type":"object"},"index":{"description":"0-based position in the request array","type":"integer"},"link":{"description":"The created or updated link (present when status is success)","type":"object"},"status":{"enum":["success","error"],"type":"string"}},"type":"object"},"title":"LinkBulkResult","type":"array"},"LinkCreateOrUpdateRequest":{"description":"POST body for creating or updating an link","example":{"url":"www.somelink.com","workspace_id":33},"properties":{"fb_pixel_id":{"description":"fb_pixel_id","type":"string"},"tiktok_pixel_id":{"description":"tiktok_pixel_id","type":"string"},"hide_referrer":{"description":"hide_referrer","type":"boolean"},"expiry_datetime":{"description":"When the link expires (ISO 8601). After this time visitors are sent to `expiry_destination`. The year must be between 2000 and 2100.","example":"2026-12-31T23:59:59Z","format":"date-time","type":"string"},"expiry_destination":{"description":"Where visitors are sent once the link has expired (by date or by click count). Must start with `http`.","example":"https://example.com/expired","format":"uri","type":"string"},"rules":{"items":{"properties":{"matches":{"type":"string"},"percentage":{"type":"string"},"rule_url":{"type":"string"},"url":{"type":"string"},"what":{"type":"string"}},"type":"object"},"type":"array"},"cloaking":{"description":"cloaking","type":"boolean"},"linkify_words":{"description":"linkify_words","type":"string"},"og_description":{"description":"og_description","type":"string"},"body_tags":{"description":"body_tags","type":"string"},"spam":{"description":"spam","type":"boolean"},"og_title":{"description":"og_title","type":"string"},"note":{"description":"note","type":"string"},"name":{"description":"name","type":"string"},"id":{"description":"Link ID. Required to update an existing link","type":"integer"},"gtm_id":{"description":"gtm_id","type":"string"},"og_image":{"description":"og_image","type":"string"},"block_bots":{"description":"block_bots","type":"boolean"},"utm_content":{"description":"utm_content","type":"string"},"enabled":{"description":"enabled","type":"boolean"},"url":{"description":"URL. Required to create a new link.","example":"www.somelink.com","format":"uri","type":"string"},"replacements":{"description":"replacements","type":"string"},"deleted":{"description":"deleted","type":"boolean"},"expiry_clicks":{"description":"Expire the link after this many clicks; visitors are then sent to `expiry_destination`.","example":1000,"type":"integer"},"workspace_id":{"description":"Workspace ID","type":"integer"},"utm_source":{"description":"utm_source","type":"string"},"slug":{"description":"slug","type":"string"},"domain":{"description":"domain","type":"string"},"forward_params":{"description":"forward_params","type":"boolean"},"utm_medium":{"description":"utm_medium","type":"string"},"head_tags":{"description":"head_tags","type":"string"},"ga4_tag_id":{"description":"ga4_tag_id","type":"string"},"utm_term":{"description":"utm_term","type":"string"},"utm_campaign":{"description":"utm_campaign","type":"string"}},"title":"LinkCreateOrUpdateRequest","type":"object"},"LinkListResponse":{"description":"Paginated list of links in a workspace, with click statistics.","example":{"links":[{"clicks_thirty_days":64,"clicks_today":3,"clicks_total":215,"domain":"go.yourcompany.com","enabled":true,"full_url":"https://go.yourcompany.com/promo","human_clicks_thirty_days":51,"human_clicks_today":2,"human_clicks_total":168,"id":30,"name":"Summer promo","slug":"/promo","sparkline":[0,2,5,1,8,3],"url":"https://www.example.com","workspace_id":42}],"page_number":1,"page_size":1000,"total_entries":1,"total_pages":1,"workspace_link_count":1},"properties":{"links":{"items":{"description":"A link with click statistics, as returned by workspace link endpoints.","properties":{"fb_pixel_id":{"nullable":true,"type":"string"},"human_clicks_total":{"description":"Lifetime clicks with no bot signal — the subset of `clicks_total` where neither a bot user-agent nor a verified-bot category was detected. Recorded from 2019 onward.","type":"integer"},"sparkline":{"description":"Daily human clicks over the last 30 days, oldest first.","items":{"type":"integer"},"type":"array"},"clicks_thirty_days":{"description":"Clicks in the last 30 days, including bot traffic.","type":"integer"},"tiktok_pixel_id":{"nullable":true,"type":"string"},"hide_referrer":{"nullable":true,"type":"boolean"},"rules":{"items":{"$ref":"#/components/schemas/Rule"},"nullable":true,"type":"array"},"cloaking":{"nullable":true,"type":"boolean"},"linkify_words":{"nullable":true,"type":"string"},"full_url":{"format":"uri","type":"string"},"clicks_today":{"description":"Clicks so far today (UTC), including bot traffic.","type":"integer"},"og_description":{"nullable":true,"type":"string"},"body_tags":{"nullable":true,"type":"string"},"og_title":{"nullable":true,"type":"string"},"note":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"id":{"nullable":true,"type":"integer"},"gtm_id":{"nullable":true,"type":"string"},"og_image":{"nullable":true,"type":"string"},"block_bots":{"nullable":true,"type":"boolean"},"clicks_total":{"description":"Lifetime clicks, including bot traffic.","type":"integer"},"human_clicks_thirty_days":{"description":"Clicks in the last 30 days with no bot signal — the subset of `clicks_thirty_days`.","type":"integer"},"utm_content":{"nullable":true,"type":"string"},"human_clicks_today":{"description":"Clicks so far today (UTC) with no bot signal.","type":"integer"},"enabled":{"nullable":true,"type":"boolean"},"url":{"format":"uri","type":"string"},"replacements":{"nullable":true,"type":"string"},"deleted":{"nullable":true,"type":"boolean"},"workspace_id":{"nullable":true,"type":"integer"},"public_analytics":{"nullable":true,"type":"boolean"},"utm_source":{"nullable":true,"type":"string"},"slug":{"nullable":true,"type":"string"},"domain":{"nullable":true,"type":"string"},"forward_params":{"nullable":true,"type":"boolean"},"utm_medium":{"nullable":true,"type":"string"},"head_tags":{"nullable":true,"type":"string"},"ga4_tag_id":{"nullable":true,"type":"string"},"utm_term":{"nullable":true,"type":"string"},"utm_campaign":{"nullable":true,"type":"string"},"human_clicks_previous_day":{"description":"Clicks yesterday (UTC) with no bot signal.","type":"integer"}},"title":"WorkspaceLink","type":"object"},"type":"array"},"page_number":{"type":"integer"},"page_size":{"type":"integer"},"total_entries":{"type":"integer"},"total_pages":{"type":"integer"},"total_rows":{"type":"integer"},"workspace_link_count":{"type":"integer"}},"title":"LinkListResponse","type":"object"},"NotAuthorized":{"example":"Not authorized","title":"NotAuthorized","type":"string"},"RateLimitError":{"description":"Rate limit exceeded error","properties":{"current_usage":{"type":"integer"},"error":{"type":"string"},"limit":{"type":"integer"},"message":{"type":"string"}},"title":"RateLimitError","type":"object"},"Rule":{"example":{},"properties":{"matches":{"nullable":true,"type":"string"},"percentage":{"nullable":true,"type":"integer"},"url":{"nullable":true,"type":"string"},"what":{"nullable":true,"type":"string"}},"title":"Rule","type":"object"},"UpdateFaviconRequest":{"properties":{"favicon_url":{"description":"URL to favicon image","format":"uri","type":"string"}},"title":"UpdateFaviconRequest","type":"object"},"WebhookErrorResponse":{"description":"Error response","properties":{"error":{"example":"Missing or invalid parameters","type":"string"}},"title":"WebhookErrorResponse","type":"object"},"WebhookSubscribeRequest":{"description":"Request body for subscribing a webhook","properties":{"url":{"description":"The webhook URL to receive click notifications","example":"https://hooks.zapier.com/hooks/catch/123456/abcdef/","format":"uri","type":"string"}},"required":["url"],"title":"WebhookSubscribeRequest","type":"object"},"WebhookSubscribeResponse":{"description":"Response after subscribing a webhook","properties":{"id":{"description":"The webhook URL (used as the hook ID for unsubscribing)","example":"https://hooks.zapier.com/hooks/catch/123456/abcdef/","type":"string"}},"title":"WebhookSubscribeResponse","type":"object"},"WebhooksListResponse":{"description":"List of webhook subscriptions","items":{"properties":{"id":{"description":"The webhook URL","example":"https://hooks.zapier.com/hooks/catch/123456/abcdef/","type":"string"}},"type":"object"},"title":"WebhooksListResponse","type":"array"},"WorkspaceLink":{"description":"A link with click statistics, as returned by workspace link endpoints.","properties":{"fb_pixel_id":{"nullable":true,"type":"string"},"human_clicks_total":{"description":"Lifetime clicks with no bot signal — the subset of `clicks_total` where neither a bot user-agent nor a verified-bot category was detected. Recorded from 2019 onward.","type":"integer"},"sparkline":{"description":"Daily human clicks over the last 30 days, oldest first.","items":{"type":"integer"},"type":"array"},"clicks_thirty_days":{"description":"Clicks in the last 30 days, including bot traffic.","type":"integer"},"tiktok_pixel_id":{"nullable":true,"type":"string"},"hide_referrer":{"nullable":true,"type":"boolean"},"rules":{"items":{"$ref":"#/components/schemas/Rule"},"nullable":true,"type":"array"},"cloaking":{"nullable":true,"type":"boolean"},"linkify_words":{"nullable":true,"type":"string"},"full_url":{"format":"uri","type":"string"},"clicks_today":{"description":"Clicks so far today (UTC), including bot traffic.","type":"integer"},"og_description":{"nullable":true,"type":"string"},"body_tags":{"nullable":true,"type":"string"},"og_title":{"nullable":true,"type":"string"},"note":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"id":{"nullable":true,"type":"integer"},"gtm_id":{"nullable":true,"type":"string"},"og_image":{"nullable":true,"type":"string"},"block_bots":{"nullable":true,"type":"boolean"},"clicks_total":{"description":"Lifetime clicks, including bot traffic.","type":"integer"},"human_clicks_thirty_days":{"description":"Clicks in the last 30 days with no bot signal — the subset of `clicks_thirty_days`.","type":"integer"},"utm_content":{"nullable":true,"type":"string"},"human_clicks_today":{"description":"Clicks so far today (UTC) with no bot signal.","type":"integer"},"enabled":{"nullable":true,"type":"boolean"},"url":{"format":"uri","type":"string"},"replacements":{"nullable":true,"type":"string"},"deleted":{"nullable":true,"type":"boolean"},"workspace_id":{"nullable":true,"type":"integer"},"public_analytics":{"nullable":true,"type":"boolean"},"utm_source":{"nullable":true,"type":"string"},"slug":{"nullable":true,"type":"string"},"domain":{"nullable":true,"type":"string"},"forward_params":{"nullable":true,"type":"boolean"},"utm_medium":{"nullable":true,"type":"string"},"head_tags":{"nullable":true,"type":"string"},"ga4_tag_id":{"nullable":true,"type":"string"},"utm_term":{"nullable":true,"type":"string"},"utm_campaign":{"nullable":true,"type":"string"},"human_clicks_previous_day":{"description":"Clicks yesterday (UTC) with no bot signal.","type":"integer"}},"title":"WorkspaceLink","type":"object"}},"securitySchemes":{"apiKey":{"description":"Your API key, passed as the `api_key` query parameter.","in":"query","name":"api_key","type":"apiKey"},"basicAuth":{"description":"HTTP Basic authentication with your API key as the username and an empty password.","scheme":"basic","type":"http"},"bearerAuth":{"description":"Your API key, passed as a Bearer token in the `Authorization` header.","scheme":"bearer","type":"http"}}},"info":{"description":"The Linkly URL shortener API (also known as a link shortener API) lets you create and manage short links, track clicks, configure custom domains, and subscribe to webhooks — all programmatically.\n\n> **You don't need to read this documentation to use the API.** The Linkly interface shows the exact API request inline whenever you create a link or pull analytics — just copy and paste it directly into your code or terminal.\n\nLooking for step-by-step guides, tutorials, and FAQs? The [Linkly API documentation](https://linklyhq.com/support/api) covers a broader range of topics. This page is the complete endpoint reference.\n\n## Authentication\n\nAll API requests require an API key. You can find your API key in your [Linkly workspace settings](https://app.linklyhq.com).\n\nThe recommended way is to pass it as a Bearer token in the `Authorization` header:\n\n```\nAuthorization: Bearer YOUR_API_KEY\n```\n\nYou can also use HTTP Basic Auth, with your API key as the username and an empty password:\n\n```\nAuthorization: Basic base64(YOUR_API_KEY:)\n```\n\nOr, for quick testing, pass it as the `api_key` query parameter. Prefer the header in production — query-string keys can leak into server logs, browser history, and `Referer` headers:\n\n```\nGET https://api.linklyhq.com/api/v1/workspaces?api_key=YOUR_API_KEY\n```\n\nA request with a missing or invalid API key returns `401`; a request for a workspace your key cannot access returns `404` (workspaces you don't belong to are not distinguished from ones that don't exist); plan- or permission-related failures return `403`. All errors share the JSON shape documented under **Errors** below.\n\n## Base URL\n\n```\nhttps://api.linklyhq.com/api/v1\n```\n\n## Workspaces\n\nMost endpoints are scoped to a **workspace**. Use `GET /workspaces` to list your available workspaces and retrieve their IDs.\n\n## Rate Limits\n\nAPI requests are rate-limited. When you exceed a limit, the API returns `429 Too Many Requests`. Check the response body for your current usage and limit.\n\nThe analytics endpoints (clicks, counters and exports, including link exports) also draw on a usage allowance that resets each billing period. When a workspace on a paid plan uses all of its analytics requests, an API pack is added to its subscription automatically so requests keep working; packs can also be added from the Billing page. See [Analytics API limits](https://linklyhq.com/support/analytics-api) for details.\n\n## Errors\n\nErrors return the appropriate HTTP status code and a JSON body with a human-readable `error` message and a stable, machine-readable `code` you can branch on:\n\n```json\n{ \"error\": \"Not authorized\", \"code\": \"unauthorized\" }\n```\n\n| Status | `code` | Meaning |\n| --- | --- | --- |\n| `400` | `bad_request` | Missing or malformed parameters. |\n| `401` | `unauthorized` | Missing or invalid API key. |\n| `403` | `forbidden` | Your plan or permissions don't allow this action. |\n| `404` | `not_found` | The resource doesn't exist, or your key can't access it. |\n| `429` | `rate_limit_exceeded` | You've exceeded a rate or usage limit. |\n| `500` | `internal_error` | Something went wrong on our side. |\n\nValidation failures return `400` and may include field-level details (e.g. `{ \"slug\": [\"is invalid\"] }`) in place of the envelope above.\n","title":"Linkly URL Shortener API","version":"1.3","x-logo":{"altText":"Linkly","url":"https://linklyhq.com/brand/linkly-logo.svg"}},"openapi":"3.0.0","paths":{"/api/v1/conversions":{"get":{"callbacks":{},"deprecated":false,"description":"List the workspace's conversions.\n\nWithout `after` or `since`, returns the most recent conversions first (by `occurred_at`).\n\n### Paging through every conversion\n\nPass `since`, `after`, or both, and conversions come back in the order Linkly recorded them, oldest first. To walk the full history, request a page with `since` set to any date before your first conversion (for example `2020-01-01`), then keep requesting with `after` set to the `id` of the last conversion you received for as long as `has_more` is `true`. To sync incrementally, set `since` to when you last synced: conversions are never renumbered, and a conversion reported late (a webhook arriving days after the sale) is recorded, and so returned, at the time it arrives rather than at its `occurred_at`.","operationId":"listConversions","parameters":[{"description":"The ID of the workspace. Required when authenticating with an API key. Omit it with an OAuth token, which is bound to one workspace.","example":"42","in":"query","name":"workspace_id","required":false,"schema":{"type":"string"}},{"description":"Maximum conversions to return (1–1000, default 100)","example":100,"in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"Return conversions recorded after this conversion `id`, oldest first. Use the `id` of the last conversion on the previous page.","example":"01KYPH20SEJY4HQSCPMWW60QE0","in":"query","name":"after","required":false,"schema":{"type":"string"}},{"description":"Return conversions Linkly recorded at or after this time, oldest first. An ISO 8601 date (`2026-07-29`) or date-time (`2026-07-29T10:30:00Z`); a date-time without an offset is read as UTC.","example":"2026-07-29T10:30:00Z","in":"query","name":"since","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"conversions":{"items":{"properties":{"amount_cents":{"example":4999,"nullable":true,"type":"integer"},"click_id":{"description":"The click the conversion is attributed to.","example":"01KYPGEEPJSPR3S564QRBDGA1W","type":"string"},"country":{"example":"US","nullable":true,"type":"string"},"currency":{"example":"USD","nullable":true,"type":"string"},"event_id":{"example":"shopify-1234","nullable":true,"type":"string"},"event_name":{"example":"purchase","type":"string"},"event_type":{"example":"sale","type":"string"},"external_id":{"example":"customer-42","nullable":true,"type":"string"},"id":{"description":"ULID. Sorts chronologically, so ids are ordered by creation.","example":"01KYPH20SEJY4HQSCPMWW60QE0","type":"string"},"inserted_at":{"description":"When Linkly stored it. UTC, ISO 8601 without an offset (`YYYY-MM-DDTHH:MM:SS`), unlike `occurred_at`.","example":"2026-07-29T10:30:01","type":"string"},"ip_source":{"description":"Whose address was recorded. `server` means the connecting address belonged to your backend or a platform relay, so it is excluded from geographic reporting. The address itself is never returned.","enum":["visitor","server","unknown"],"example":"visitor","type":"string"},"link_id":{"description":"The link the conversion is attributed to.","example":41657524,"type":"integer"},"metadata":{"nullable":true,"type":"object"},"occurred_at":{"description":"When the conversion happened, UTC with offset.","example":"2026-07-29T10:30:00.123456Z","format":"date-time","type":"string"},"source":{"description":"Which integration reported it.","example":"api","type":"string"}},"required":["id","link_id","click_id","event_type","event_name","source","occurred_at","inserted_at"],"title":"Conversion","type":"object"},"type":"array"},"has_more":{"description":"True when more conversions follow this page. When paging with `since` or `after`, request the next page with `after` set to the last `id` here.","example":false,"type":"boolean"}},"required":["conversions","has_more"],"title":"ConversionList","type":"object"}}},"description":"Conversion list"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"`workspace_id` missing for an API-key caller (code `workspace_required`), or an `after` or `since` that does not parse (code `invalid_params`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Unauthorized"}},"security":[{"apiKey":[]}],"summary":"List conversions","tags":["Conversions"]},"post":{"callbacks":{},"deprecated":false,"description":"Report a conversion — a purchase, signup, or custom event that happened on your site after someone clicked a Linkly link.\n\nPass the `linkly_cid` your landing page captured to attribute the conversion to the originating link. A conversion that cannot be attributed — no `linkly_cid`, an unrecognised one, and no earlier attributed event for the same `external_id` — is **discarded**: the call returns `202` with `attributed: false` and nothing is stored. It is not an error, so do not retry it; check that your landing page is capturing and forwarding `linkly_cid`.\n\n### Leads and sales\n\nSet `event_type` to `lead` for signups, trials and demo requests, `sale` when money changes hands, or `custom` for anything else. The type drives the clicks → leads → sales funnel.\n\nSend `external_id` — your own customer identifier — on every event. A `lead` reported with both an `linkly_cid` and an `external_id` ties that customer to the link, and later events for the same `external_id` inherit the attribution automatically. This is what makes server-side sales attributable: the purchase usually arrives from a billing webhook that never saw the `linkly_cid`. Attribution is first-touch, so a customer who later arrives via a different link keeps the credit on their original one.\n\nSupply `event_id` to make the call idempotent. Reporting the same `event_id` twice returns `200` with the original conversion instead of creating a duplicate, so a retrying client is safe.","operationId":"createConversion","parameters":[{"description":"The ID of the workspace. Required when authenticating with an API key. Omit it with an OAuth token, which is bound to one workspace.","example":"42","in":"query","name":"workspace_id","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"description":"A conversion to record","properties":{"amount_cents":{"description":"Value in the smallest currency unit. May be negative to record a refund or chargeback, which nets against earlier revenue.","example":4999,"type":"integer"},"country":{"description":"Two-letter country code for the conversion. Inferred for browser-side calls; supply it explicitly from a server-side integration, where the connecting address is your own infrastructure rather than the customer's.","example":"US","type":"string"},"currency":{"description":"ISO 4217 currency code. Defaults to USD.","example":"USD","type":"string"},"event_id":{"description":"Your identifier for this event. Used as an idempotency key — reporting the same value twice will not create a second conversion. Applies to any event type, not just purchases.","example":"shopify-1234","type":"string"},"event_name":{"description":"What happened, e.g. `purchase`, `signup`, `trial_started`","example":"purchase","type":"string"},"event_type":{"description":"Coarse type driving the funnel. `lead` establishes customer identity, `sale` records revenue. Defaults to `custom`.","enum":["lead","sale","custom"],"example":"sale","type":"string"},"external_id":{"description":"Your identifier for the customer. Send it on every event: it is what links a later server-side sale back to the click that produced the signup.","example":"customer-42","type":"string"},"linkly_cid":{"description":"The attribution token captured from the landing page URL. Omit if unavailable — the conversion is then recorded without a link attribution.","example":"2on1Y.01KYPGEEPJSPR3S564QRBDGA1W","type":"string"},"metadata":{"description":"Arbitrary JSON, up to 10,000 bytes encoded.","example":{"sku":"ABC-123"},"type":"object"},"occurred_at":{"description":"When the conversion happened. Defaults to now.","example":"2026-07-29T10:30:00Z","format":"date-time","type":"string"},"visitor_ip":{"description":"The end customer's IP, when your server has it. Omit unless you do — for server-side calls Linkly otherwise records the connecting address as your server, not the customer, and excludes it from geographic reporting. Sending this asserts you have a lawful basis to share it. Never returned by the API.","example":"203.0.113.42","type":"string"}},"required":["event_name"],"title":"ConversionCreateRequest","type":"object"}},"application/x-www-form-urlencoded":{"schema":{"description":"A conversion to record","properties":{"amount_cents":{"description":"Value in the smallest currency unit. May be negative to record a refund or chargeback, which nets against earlier revenue.","example":4999,"type":"integer"},"country":{"description":"Two-letter country code for the conversion. Inferred for browser-side calls; supply it explicitly from a server-side integration, where the connecting address is your own infrastructure rather than the customer's.","example":"US","type":"string"},"currency":{"description":"ISO 4217 currency code. Defaults to USD.","example":"USD","type":"string"},"event_id":{"description":"Your identifier for this event. Used as an idempotency key — reporting the same value twice will not create a second conversion. Applies to any event type, not just purchases.","example":"shopify-1234","type":"string"},"event_name":{"description":"What happened, e.g. `purchase`, `signup`, `trial_started`","example":"purchase","type":"string"},"event_type":{"description":"Coarse type driving the funnel. `lead` establishes customer identity, `sale` records revenue. Defaults to `custom`.","enum":["lead","sale","custom"],"example":"sale","type":"string"},"external_id":{"description":"Your identifier for the customer. Send it on every event: it is what links a later server-side sale back to the click that produced the signup.","example":"customer-42","type":"string"},"linkly_cid":{"description":"The attribution token captured from the landing page URL. Omit if unavailable — the conversion is then recorded without a link attribution.","example":"2on1Y.01KYPGEEPJSPR3S564QRBDGA1W","type":"string"},"metadata":{"description":"Arbitrary JSON, up to 10,000 bytes encoded.","example":{"sku":"ABC-123"},"type":"object"},"occurred_at":{"description":"When the conversion happened. Defaults to now.","example":"2026-07-29T10:30:00Z","format":"date-time","type":"string"},"visitor_ip":{"description":"The end customer's IP, when your server has it. Omit unless you do — for server-side calls Linkly otherwise records the connecting address as your server, not the customer, and excludes it from geographic reporting. Sending this asserts you have a lawful basis to share it. Never returned by the API.","example":"203.0.113.42","type":"string"}},"required":["event_name"],"title":"ConversionCreateRequest","type":"object"}},"multipart/form-data":{"schema":{"description":"A conversion to record","properties":{"amount_cents":{"description":"Value in the smallest currency unit. May be negative to record a refund or chargeback, which nets against earlier revenue.","example":4999,"type":"integer"},"country":{"description":"Two-letter country code for the conversion. Inferred for browser-side calls; supply it explicitly from a server-side integration, where the connecting address is your own infrastructure rather than the customer's.","example":"US","type":"string"},"currency":{"description":"ISO 4217 currency code. Defaults to USD.","example":"USD","type":"string"},"event_id":{"description":"Your identifier for this event. Used as an idempotency key — reporting the same value twice will not create a second conversion. Applies to any event type, not just purchases.","example":"shopify-1234","type":"string"},"event_name":{"description":"What happened, e.g. `purchase`, `signup`, `trial_started`","example":"purchase","type":"string"},"event_type":{"description":"Coarse type driving the funnel. `lead` establishes customer identity, `sale` records revenue. Defaults to `custom`.","enum":["lead","sale","custom"],"example":"sale","type":"string"},"external_id":{"description":"Your identifier for the customer. Send it on every event: it is what links a later server-side sale back to the click that produced the signup.","example":"customer-42","type":"string"},"linkly_cid":{"description":"The attribution token captured from the landing page URL. Omit if unavailable — the conversion is then recorded without a link attribution.","example":"2on1Y.01KYPGEEPJSPR3S564QRBDGA1W","type":"string"},"metadata":{"description":"Arbitrary JSON, up to 10,000 bytes encoded.","example":{"sku":"ABC-123"},"type":"object"},"occurred_at":{"description":"When the conversion happened. Defaults to now.","example":"2026-07-29T10:30:00Z","format":"date-time","type":"string"},"visitor_ip":{"description":"The end customer's IP, when your server has it. Omit unless you do — for server-side calls Linkly otherwise records the connecting address as your server, not the customer, and excludes it from geographic reporting. Sending this asserts you have a lawful basis to share it. Never returned by the API.","example":"203.0.113.42","type":"string"}},"required":["event_name"],"title":"ConversionCreateRequest","type":"object"}}},"description":"Conversion","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"amount_cents":{"example":4999,"nullable":true,"type":"integer"},"click_id":{"description":"The click the conversion is attributed to.","example":"01KYPGEEPJSPR3S564QRBDGA1W","type":"string"},"country":{"example":"US","nullable":true,"type":"string"},"currency":{"example":"USD","nullable":true,"type":"string"},"event_id":{"example":"shopify-1234","nullable":true,"type":"string"},"event_name":{"example":"purchase","type":"string"},"event_type":{"example":"sale","type":"string"},"external_id":{"example":"customer-42","nullable":true,"type":"string"},"id":{"description":"ULID. Sorts chronologically, so ids are ordered by creation.","example":"01KYPH20SEJY4HQSCPMWW60QE0","type":"string"},"inserted_at":{"description":"When Linkly stored it. UTC, ISO 8601 without an offset (`YYYY-MM-DDTHH:MM:SS`), unlike `occurred_at`.","example":"2026-07-29T10:30:01","type":"string"},"ip_source":{"description":"Whose address was recorded. `server` means the connecting address belonged to your backend or a platform relay, so it is excluded from geographic reporting. The address itself is never returned.","enum":["visitor","server","unknown"],"example":"visitor","type":"string"},"link_id":{"description":"The link the conversion is attributed to.","example":41657524,"type":"integer"},"metadata":{"nullable":true,"type":"object"},"occurred_at":{"description":"When the conversion happened, UTC with offset.","example":"2026-07-29T10:30:00.123456Z","format":"date-time","type":"string"},"source":{"description":"Which integration reported it.","example":"api","type":"string"}},"required":["id","link_id","click_id","event_type","event_name","source","occurred_at","inserted_at"],"title":"Conversion","type":"object"}}},"description":"Already recorded — the existing conversion for this event_id"},"201":{"content":{"application/json":{"schema":{"properties":{"amount_cents":{"example":4999,"nullable":true,"type":"integer"},"click_id":{"description":"The click the conversion is attributed to.","example":"01KYPGEEPJSPR3S564QRBDGA1W","type":"string"},"country":{"example":"US","nullable":true,"type":"string"},"currency":{"example":"USD","nullable":true,"type":"string"},"event_id":{"example":"shopify-1234","nullable":true,"type":"string"},"event_name":{"example":"purchase","type":"string"},"event_type":{"example":"sale","type":"string"},"external_id":{"example":"customer-42","nullable":true,"type":"string"},"id":{"description":"ULID. Sorts chronologically, so ids are ordered by creation.","example":"01KYPH20SEJY4HQSCPMWW60QE0","type":"string"},"inserted_at":{"description":"When Linkly stored it. UTC, ISO 8601 without an offset (`YYYY-MM-DDTHH:MM:SS`), unlike `occurred_at`.","example":"2026-07-29T10:30:01","type":"string"},"ip_source":{"description":"Whose address was recorded. `server` means the connecting address belonged to your backend or a platform relay, so it is excluded from geographic reporting. The address itself is never returned.","enum":["visitor","server","unknown"],"example":"visitor","type":"string"},"link_id":{"description":"The link the conversion is attributed to.","example":41657524,"type":"integer"},"metadata":{"nullable":true,"type":"object"},"occurred_at":{"description":"When the conversion happened, UTC with offset.","example":"2026-07-29T10:30:00.123456Z","format":"date-time","type":"string"},"source":{"description":"Which integration reported it.","example":"api","type":"string"}},"required":["id","link_id","click_id","event_type","event_name","source","occurred_at","inserted_at"],"title":"Conversion","type":"object"}}},"description":"Conversion recorded"},"202":{"content":{"application/json":{"schema":{"description":"The conversion could not be attributed to a link and was discarded. Not an error: do not retry.","properties":{"attributed":{"enum":[false],"example":false,"type":"boolean"},"message":{"example":"Conversion could not be attributed to a link and was not recorded. Check that linkly_cid is being captured and sent.","type":"string"}},"required":["attributed","message"],"title":"ConversionUnattributed","type":"object"}}},"description":"Not attributed: understood but not recorded"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Invalid parameters, or `workspace_id` missing for an API-key caller (code `workspace_required`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not available on your plan"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Validation failed"}},"security":[{"apiKey":[]}],"summary":"Report a conversion","tags":["Conversions"]}},"/api/v1/domains":{"post":{"callbacks":{},"deprecated":false,"description":"Add a new custom domain to your workspace. You must configure a CNAME DNS record pointing to domains.linklyhq.com before adding the domain.","operationId":"createDomain","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"description":"POST body for creating a Domain","example":{"name":"link.mydomain.com","workspace_id":33},"properties":{"name":{"description":"name","type":"string"},"workspace_id":{"description":"Workspace ID","type":"integer"}},"required":["workspace_id"],"title":"DomainCreateRequest","type":"object"}},"application/x-www-form-urlencoded":{"schema":{"description":"POST body for creating a Domain","example":{"name":"link.mydomain.com","workspace_id":33},"properties":{"name":{"description":"name","type":"string"},"workspace_id":{"description":"Workspace ID","type":"integer"}},"required":["workspace_id"],"title":"DomainCreateRequest","type":"object"}},"multipart/form-data":{"schema":{"description":"POST body for creating a Domain","example":{"name":"link.mydomain.com","workspace_id":33},"properties":{"name":{"description":"name","type":"string"},"workspace_id":{"description":"Workspace ID","type":"integer"}},"required":["workspace_id"],"title":"DomainCreateRequest","type":"object"}}},"description":"Parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Domain"}}},"description":"Domain"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not Found"}},"security":[{"apiKey":[]}],"summary":"Add a custom domain","tags":["Domains"]}},"/api/v1/get_link/{id}":{"get":{"callbacks":{},"deprecated":false,"description":"Retrieve details for a specific link by ID.","operationId":"getWorkspaceLink","parameters":[{"description":"The id of the Link","example":24,"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"description":"Response schema for getting a single link","properties":{"base62_id":{"type":"string"},"clicks_count":{"description":"Lifetime click count for this link, including bot traffic","type":"integer"},"domain":{"nullable":true,"type":"object"},"domains":{"items":{"type":"object"},"type":"array"},"link":{"description":"A link with click statistics, as returned by workspace link endpoints.","properties":{"fb_pixel_id":{"nullable":true,"type":"string"},"human_clicks_total":{"description":"Lifetime clicks with no bot signal — the subset of `clicks_total` where neither a bot user-agent nor a verified-bot category was detected. Recorded from 2019 onward.","type":"integer"},"sparkline":{"description":"Daily human clicks over the last 30 days, oldest first.","items":{"type":"integer"},"type":"array"},"clicks_thirty_days":{"description":"Clicks in the last 30 days, including bot traffic.","type":"integer"},"tiktok_pixel_id":{"nullable":true,"type":"string"},"hide_referrer":{"nullable":true,"type":"boolean"},"rules":{"items":{"$ref":"#/components/schemas/Rule"},"nullable":true,"type":"array"},"cloaking":{"nullable":true,"type":"boolean"},"linkify_words":{"nullable":true,"type":"string"},"full_url":{"format":"uri","type":"string"},"clicks_today":{"description":"Clicks so far today (UTC), including bot traffic.","type":"integer"},"og_description":{"nullable":true,"type":"string"},"body_tags":{"nullable":true,"type":"string"},"og_title":{"nullable":true,"type":"string"},"note":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"id":{"nullable":true,"type":"integer"},"gtm_id":{"nullable":true,"type":"string"},"og_image":{"nullable":true,"type":"string"},"block_bots":{"nullable":true,"type":"boolean"},"clicks_total":{"description":"Lifetime clicks, including bot traffic.","type":"integer"},"human_clicks_thirty_days":{"description":"Clicks in the last 30 days with no bot signal — the subset of `clicks_thirty_days`.","type":"integer"},"utm_content":{"nullable":true,"type":"string"},"human_clicks_today":{"description":"Clicks so far today (UTC) with no bot signal.","type":"integer"},"enabled":{"nullable":true,"type":"boolean"},"url":{"format":"uri","type":"string"},"replacements":{"nullable":true,"type":"string"},"deleted":{"nullable":true,"type":"boolean"},"workspace_id":{"nullable":true,"type":"integer"},"public_analytics":{"nullable":true,"type":"boolean"},"utm_source":{"nullable":true,"type":"string"},"slug":{"nullable":true,"type":"string"},"domain":{"nullable":true,"type":"string"},"forward_params":{"nullable":true,"type":"boolean"},"utm_medium":{"nullable":true,"type":"string"},"head_tags":{"nullable":true,"type":"string"},"ga4_tag_id":{"nullable":true,"type":"string"},"utm_term":{"nullable":true,"type":"string"},"utm_campaign":{"nullable":true,"type":"string"},"human_clicks_previous_day":{"description":"Clicks yesterday (UTC) with no bot signal.","type":"integer"}},"title":"WorkspaceLink","type":"object"}},"title":"GetLinkResponse","type":"object"}}},"description":"Link"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"}},"security":[{"apiKey":[]}],"summary":"Get link details","tags":["Links"]}},"/api/v1/link":{"post":{"callbacks":{},"deprecated":false,"description":"Create a new shortened link or update an existing one. To create: provide `url` and `workspace_id`. To update: provide `id` and any fields to change. Supports custom slugs, UTM parameters, retargeting pixels, Open Graph metadata, and redirect rules.","operationId":"createOrUpdateLink","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"description":"POST body for creating or updating an link","example":{"url":"www.somelink.com","workspace_id":33},"properties":{"fb_pixel_id":{"description":"fb_pixel_id","type":"string"},"tiktok_pixel_id":{"description":"tiktok_pixel_id","type":"string"},"hide_referrer":{"description":"hide_referrer","type":"boolean"},"expiry_datetime":{"description":"When the link expires (ISO 8601). After this time visitors are sent to `expiry_destination`. The year must be between 2000 and 2100.","example":"2026-12-31T23:59:59Z","format":"date-time","type":"string"},"expiry_destination":{"description":"Where visitors are sent once the link has expired (by date or by click count). Must start with `http`.","example":"https://example.com/expired","format":"uri","type":"string"},"rules":{"items":{"properties":{"matches":{"type":"string"},"percentage":{"type":"string"},"rule_url":{"type":"string"},"url":{"type":"string"},"what":{"type":"string"}},"type":"object"},"type":"array"},"cloaking":{"description":"cloaking","type":"boolean"},"linkify_words":{"description":"linkify_words","type":"string"},"og_description":{"description":"og_description","type":"string"},"body_tags":{"description":"body_tags","type":"string"},"spam":{"description":"spam","type":"boolean"},"og_title":{"description":"og_title","type":"string"},"note":{"description":"note","type":"string"},"name":{"description":"name","type":"string"},"id":{"description":"Link ID. Required to update an existing link","type":"integer"},"gtm_id":{"description":"gtm_id","type":"string"},"og_image":{"description":"og_image","type":"string"},"block_bots":{"description":"block_bots","type":"boolean"},"utm_content":{"description":"utm_content","type":"string"},"enabled":{"description":"enabled","type":"boolean"},"url":{"description":"URL. Required to create a new link.","example":"www.somelink.com","format":"uri","type":"string"},"replacements":{"description":"replacements","type":"string"},"deleted":{"description":"deleted","type":"boolean"},"expiry_clicks":{"description":"Expire the link after this many clicks; visitors are then sent to `expiry_destination`.","example":1000,"type":"integer"},"workspace_id":{"description":"Workspace ID","type":"integer"},"utm_source":{"description":"utm_source","type":"string"},"slug":{"description":"slug","type":"string"},"domain":{"description":"domain","type":"string"},"forward_params":{"description":"forward_params","type":"boolean"},"utm_medium":{"description":"utm_medium","type":"string"},"head_tags":{"description":"head_tags","type":"string"},"ga4_tag_id":{"description":"ga4_tag_id","type":"string"},"utm_term":{"description":"utm_term","type":"string"},"utm_campaign":{"description":"utm_campaign","type":"string"}},"title":"LinkCreateOrUpdateRequest","type":"object"}},"application/x-www-form-urlencoded":{"schema":{"description":"POST body for creating or updating an link","example":{"url":"www.somelink.com","workspace_id":33},"properties":{"fb_pixel_id":{"description":"fb_pixel_id","type":"string"},"tiktok_pixel_id":{"description":"tiktok_pixel_id","type":"string"},"hide_referrer":{"description":"hide_referrer","type":"boolean"},"expiry_datetime":{"description":"When the link expires (ISO 8601). After this time visitors are sent to `expiry_destination`. The year must be between 2000 and 2100.","example":"2026-12-31T23:59:59Z","format":"date-time","type":"string"},"expiry_destination":{"description":"Where visitors are sent once the link has expired (by date or by click count). Must start with `http`.","example":"https://example.com/expired","format":"uri","type":"string"},"rules":{"items":{"properties":{"matches":{"type":"string"},"percentage":{"type":"string"},"rule_url":{"type":"string"},"url":{"type":"string"},"what":{"type":"string"}},"type":"object"},"type":"array"},"cloaking":{"description":"cloaking","type":"boolean"},"linkify_words":{"description":"linkify_words","type":"string"},"og_description":{"description":"og_description","type":"string"},"body_tags":{"description":"body_tags","type":"string"},"spam":{"description":"spam","type":"boolean"},"og_title":{"description":"og_title","type":"string"},"note":{"description":"note","type":"string"},"name":{"description":"name","type":"string"},"id":{"description":"Link ID. Required to update an existing link","type":"integer"},"gtm_id":{"description":"gtm_id","type":"string"},"og_image":{"description":"og_image","type":"string"},"block_bots":{"description":"block_bots","type":"boolean"},"utm_content":{"description":"utm_content","type":"string"},"enabled":{"description":"enabled","type":"boolean"},"url":{"description":"URL. Required to create a new link.","example":"www.somelink.com","format":"uri","type":"string"},"replacements":{"description":"replacements","type":"string"},"deleted":{"description":"deleted","type":"boolean"},"expiry_clicks":{"description":"Expire the link after this many clicks; visitors are then sent to `expiry_destination`.","example":1000,"type":"integer"},"workspace_id":{"description":"Workspace ID","type":"integer"},"utm_source":{"description":"utm_source","type":"string"},"slug":{"description":"slug","type":"string"},"domain":{"description":"domain","type":"string"},"forward_params":{"description":"forward_params","type":"boolean"},"utm_medium":{"description":"utm_medium","type":"string"},"head_tags":{"description":"head_tags","type":"string"},"ga4_tag_id":{"description":"ga4_tag_id","type":"string"},"utm_term":{"description":"utm_term","type":"string"},"utm_campaign":{"description":"utm_campaign","type":"string"}},"title":"LinkCreateOrUpdateRequest","type":"object"}},"multipart/form-data":{"schema":{"description":"POST body for creating or updating an link","example":{"url":"www.somelink.com","workspace_id":33},"properties":{"fb_pixel_id":{"description":"fb_pixel_id","type":"string"},"tiktok_pixel_id":{"description":"tiktok_pixel_id","type":"string"},"hide_referrer":{"description":"hide_referrer","type":"boolean"},"expiry_datetime":{"description":"When the link expires (ISO 8601). After this time visitors are sent to `expiry_destination`. The year must be between 2000 and 2100.","example":"2026-12-31T23:59:59Z","format":"date-time","type":"string"},"expiry_destination":{"description":"Where visitors are sent once the link has expired (by date or by click count). Must start with `http`.","example":"https://example.com/expired","format":"uri","type":"string"},"rules":{"items":{"properties":{"matches":{"type":"string"},"percentage":{"type":"string"},"rule_url":{"type":"string"},"url":{"type":"string"},"what":{"type":"string"}},"type":"object"},"type":"array"},"cloaking":{"description":"cloaking","type":"boolean"},"linkify_words":{"description":"linkify_words","type":"string"},"og_description":{"description":"og_description","type":"string"},"body_tags":{"description":"body_tags","type":"string"},"spam":{"description":"spam","type":"boolean"},"og_title":{"description":"og_title","type":"string"},"note":{"description":"note","type":"string"},"name":{"description":"name","type":"string"},"id":{"description":"Link ID. Required to update an existing link","type":"integer"},"gtm_id":{"description":"gtm_id","type":"string"},"og_image":{"description":"og_image","type":"string"},"block_bots":{"description":"block_bots","type":"boolean"},"utm_content":{"description":"utm_content","type":"string"},"enabled":{"description":"enabled","type":"boolean"},"url":{"description":"URL. Required to create a new link.","example":"www.somelink.com","format":"uri","type":"string"},"replacements":{"description":"replacements","type":"string"},"deleted":{"description":"deleted","type":"boolean"},"expiry_clicks":{"description":"Expire the link after this many clicks; visitors are then sent to `expiry_destination`.","example":1000,"type":"integer"},"workspace_id":{"description":"Workspace ID","type":"integer"},"utm_source":{"description":"utm_source","type":"string"},"slug":{"description":"slug","type":"string"},"domain":{"description":"domain","type":"string"},"forward_params":{"description":"forward_params","type":"boolean"},"utm_medium":{"description":"utm_medium","type":"string"},"head_tags":{"description":"head_tags","type":"string"},"ga4_tag_id":{"description":"ga4_tag_id","type":"string"},"utm_term":{"description":"utm_term","type":"string"},"utm_campaign":{"description":"utm_campaign","type":"string"}},"title":"LinkCreateOrUpdateRequest","type":"object"}}},"description":"Parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Link"}}},"description":"Link"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not Found"}},"security":[{"apiKey":[]}],"summary":"Create or update a link","tags":["Links"]}},"/api/v1/link/{id}":{"get":{"callbacks":{},"deprecated":false,"description":"Retrieve a specific link by its ID: destination, short URL, UTM parameters, rules and configuration. Click counts are not included — use getClicks for a time series, or listLinks for per-link totals.","operationId":"getLink","parameters":[{"description":"The id of the Link","example":"1454633","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Workspace ID. Optional when using OAuth2 Bearer token.","example":"42","in":"query","name":"workspace_id","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Link"}}},"description":"Link"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"}},"security":[{"apiKey":[]}],"summary":"Get link details","tags":["Links"]}},"/api/v1/link/{link_id}/webhooks":{"get":{"callbacks":{},"deprecated":false,"description":"Get all webhook subscriptions for a specific link.","operationId":"listLinkWebhooks","parameters":[{"description":"The ID of the link","example":12345,"in":"path","name":"link_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"description":"List of webhook subscriptions","items":{"properties":{"id":{"description":"The webhook URL","example":"https://hooks.zapier.com/hooks/catch/123456/abcdef/","type":"string"}},"type":"object"},"title":"WebhooksListResponse","type":"array"}}},"description":"Webhook list"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found"}},"security":[{"apiKey":[]}],"summary":"List webhooks for a link","tags":["Webhooks"]},"post":{"callbacks":{},"deprecated":false,"description":"Subscribe a webhook URL to receive events for a specific link. The endpoint receives a `POST` for each `click`, plus `link.updated` and `link.deleted` for this link. Branch on the JSON `event` field; see the Webhooks section for payload shapes.","operationId":"subscribeWebhookToLink","parameters":[{"description":"The ID of the link to subscribe to","example":12345,"in":"path","name":"link_id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"description":"Request body for subscribing a webhook","properties":{"url":{"description":"The webhook URL to receive click notifications","example":"https://hooks.zapier.com/hooks/catch/123456/abcdef/","format":"uri","type":"string"}},"required":["url"],"title":"WebhookSubscribeRequest","type":"object"}},"application/x-www-form-urlencoded":{"schema":{"description":"Request body for subscribing a webhook","properties":{"url":{"description":"The webhook URL to receive click notifications","example":"https://hooks.zapier.com/hooks/catch/123456/abcdef/","format":"uri","type":"string"}},"required":["url"],"title":"WebhookSubscribeRequest","type":"object"}},"multipart/form-data":{"schema":{"description":"Request body for subscribing a webhook","properties":{"url":{"description":"The webhook URL to receive click notifications","example":"https://hooks.zapier.com/hooks/catch/123456/abcdef/","format":"uri","type":"string"}},"required":["url"],"title":"WebhookSubscribeRequest","type":"object"}}},"description":"Webhook subscription","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"description":"Response after subscribing a webhook","properties":{"id":{"description":"The webhook URL (used as the hook ID for unsubscribing)","example":"https://hooks.zapier.com/hooks/catch/123456/abcdef/","type":"string"}},"title":"WebhookSubscribeResponse","type":"object"}}},"description":"Webhook subscribed"},"400":{"content":{"application/json":{"schema":{"description":"Error response","properties":{"error":{"example":"Missing or invalid parameters","type":"string"}},"title":"WebhookErrorResponse","type":"object"}}},"description":"Bad request"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found"}},"security":[{"apiKey":[]}],"summary":"Subscribe webhook to a link","tags":["Webhooks"]}},"/api/v1/link/{link_id}/webhooks/{hook_id}":{"delete":{"callbacks":{},"deprecated":false,"description":"Remove a webhook subscription from a link. The hook_id is the URL-encoded webhook URL.","operationId":"unsubscribeWebhookFromLink","parameters":[{"description":"The ID of the link","example":12345,"in":"path","name":"link_id","required":true,"schema":{"type":"integer"}},{"description":"The webhook URL (URL-encoded)","example":"https%3A%2F%2Fhooks.example.com%2Fabc123","in":"path","name":"hook_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Webhook unsubscribed"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found"}},"security":[{"apiKey":[]}],"summary":"Unsubscribe webhook from a link","tags":["Webhooks"]}},"/api/v1/links":{"post":{"callbacks":{},"deprecated":false,"description":"Create or update up to 1000 links in one request. The body is a JSON array where each item uses the same schema as `POST /api/v1/link` — include `id` to update, omit it to create, and provide `workspace_id` per item (required for API-key auth; ignored for OAuth, whose token is scoped to a single workspace). Returns one result per item and responds 200 even if some items fail — inspect each item's `status`.","operationId":"bulkCreateOrUpdateLinks","parameters":[],"requestBody":{"content":{"application/json":{"example":[{"name":"Nature","url":"https://nature.com","workspace_id":33},{"id":1454633,"url":"https://science.com","workspace_id":33}],"schema":{"description":"A JSON array of up to 1000 link objects to create or update.","items":{"description":"POST body for creating or updating an link","example":{"url":"www.somelink.com","workspace_id":33},"properties":{"fb_pixel_id":{"description":"fb_pixel_id","type":"string"},"tiktok_pixel_id":{"description":"tiktok_pixel_id","type":"string"},"hide_referrer":{"description":"hide_referrer","type":"boolean"},"expiry_datetime":{"description":"When the link expires (ISO 8601). After this time visitors are sent to `expiry_destination`. The year must be between 2000 and 2100.","example":"2026-12-31T23:59:59Z","format":"date-time","type":"string"},"expiry_destination":{"description":"Where visitors are sent once the link has expired (by date or by click count). Must start with `http`.","example":"https://example.com/expired","format":"uri","type":"string"},"rules":{"items":{"properties":{"matches":{"type":"string"},"percentage":{"type":"string"},"rule_url":{"type":"string"},"url":{"type":"string"},"what":{"type":"string"}},"type":"object"},"type":"array"},"cloaking":{"description":"cloaking","type":"boolean"},"linkify_words":{"description":"linkify_words","type":"string"},"og_description":{"description":"og_description","type":"string"},"body_tags":{"description":"body_tags","type":"string"},"spam":{"description":"spam","type":"boolean"},"og_title":{"description":"og_title","type":"string"},"note":{"description":"note","type":"string"},"name":{"description":"name","type":"string"},"id":{"description":"Link ID. Required to update an existing link","type":"integer"},"gtm_id":{"description":"gtm_id","type":"string"},"og_image":{"description":"og_image","type":"string"},"block_bots":{"description":"block_bots","type":"boolean"},"utm_content":{"description":"utm_content","type":"string"},"enabled":{"description":"enabled","type":"boolean"},"url":{"description":"URL. Required to create a new link.","example":"www.somelink.com","format":"uri","type":"string"},"replacements":{"description":"replacements","type":"string"},"deleted":{"description":"deleted","type":"boolean"},"expiry_clicks":{"description":"Expire the link after this many clicks; visitors are then sent to `expiry_destination`.","example":1000,"type":"integer"},"workspace_id":{"description":"Workspace ID","type":"integer"},"utm_source":{"description":"utm_source","type":"string"},"slug":{"description":"slug","type":"string"},"domain":{"description":"domain","type":"string"},"forward_params":{"description":"forward_params","type":"boolean"},"utm_medium":{"description":"utm_medium","type":"string"},"head_tags":{"description":"head_tags","type":"string"},"ga4_tag_id":{"description":"ga4_tag_id","type":"string"},"utm_term":{"description":"utm_term","type":"string"},"utm_campaign":{"description":"utm_campaign","type":"string"}},"title":"LinkCreateOrUpdateRequest","type":"object"},"maxItems":1000,"title":"LinkBulkRequest","type":"array"}},"application/x-www-form-urlencoded":{"example":[{"name":"Nature","url":"https://nature.com","workspace_id":33},{"id":1454633,"url":"https://science.com","workspace_id":33}],"schema":{"description":"A JSON array of up to 1000 link objects to create or update.","items":{"description":"POST body for creating or updating an link","example":{"url":"www.somelink.com","workspace_id":33},"properties":{"fb_pixel_id":{"description":"fb_pixel_id","type":"string"},"tiktok_pixel_id":{"description":"tiktok_pixel_id","type":"string"},"hide_referrer":{"description":"hide_referrer","type":"boolean"},"expiry_datetime":{"description":"When the link expires (ISO 8601). After this time visitors are sent to `expiry_destination`. The year must be between 2000 and 2100.","example":"2026-12-31T23:59:59Z","format":"date-time","type":"string"},"expiry_destination":{"description":"Where visitors are sent once the link has expired (by date or by click count). Must start with `http`.","example":"https://example.com/expired","format":"uri","type":"string"},"rules":{"items":{"properties":{"matches":{"type":"string"},"percentage":{"type":"string"},"rule_url":{"type":"string"},"url":{"type":"string"},"what":{"type":"string"}},"type":"object"},"type":"array"},"cloaking":{"description":"cloaking","type":"boolean"},"linkify_words":{"description":"linkify_words","type":"string"},"og_description":{"description":"og_description","type":"string"},"body_tags":{"description":"body_tags","type":"string"},"spam":{"description":"spam","type":"boolean"},"og_title":{"description":"og_title","type":"string"},"note":{"description":"note","type":"string"},"name":{"description":"name","type":"string"},"id":{"description":"Link ID. Required to update an existing link","type":"integer"},"gtm_id":{"description":"gtm_id","type":"string"},"og_image":{"description":"og_image","type":"string"},"block_bots":{"description":"block_bots","type":"boolean"},"utm_content":{"description":"utm_content","type":"string"},"enabled":{"description":"enabled","type":"boolean"},"url":{"description":"URL. Required to create a new link.","example":"www.somelink.com","format":"uri","type":"string"},"replacements":{"description":"replacements","type":"string"},"deleted":{"description":"deleted","type":"boolean"},"expiry_clicks":{"description":"Expire the link after this many clicks; visitors are then sent to `expiry_destination`.","example":1000,"type":"integer"},"workspace_id":{"description":"Workspace ID","type":"integer"},"utm_source":{"description":"utm_source","type":"string"},"slug":{"description":"slug","type":"string"},"domain":{"description":"domain","type":"string"},"forward_params":{"description":"forward_params","type":"boolean"},"utm_medium":{"description":"utm_medium","type":"string"},"head_tags":{"description":"head_tags","type":"string"},"ga4_tag_id":{"description":"ga4_tag_id","type":"string"},"utm_term":{"description":"utm_term","type":"string"},"utm_campaign":{"description":"utm_campaign","type":"string"}},"title":"LinkCreateOrUpdateRequest","type":"object"},"maxItems":1000,"title":"LinkBulkRequest","type":"array"}},"multipart/form-data":{"example":[{"name":"Nature","url":"https://nature.com","workspace_id":33},{"id":1454633,"url":"https://science.com","workspace_id":33}],"schema":{"description":"A JSON array of up to 1000 link objects to create or update.","items":{"description":"POST body for creating or updating an link","example":{"url":"www.somelink.com","workspace_id":33},"properties":{"fb_pixel_id":{"description":"fb_pixel_id","type":"string"},"tiktok_pixel_id":{"description":"tiktok_pixel_id","type":"string"},"hide_referrer":{"description":"hide_referrer","type":"boolean"},"expiry_datetime":{"description":"When the link expires (ISO 8601). After this time visitors are sent to `expiry_destination`. The year must be between 2000 and 2100.","example":"2026-12-31T23:59:59Z","format":"date-time","type":"string"},"expiry_destination":{"description":"Where visitors are sent once the link has expired (by date or by click count). Must start with `http`.","example":"https://example.com/expired","format":"uri","type":"string"},"rules":{"items":{"properties":{"matches":{"type":"string"},"percentage":{"type":"string"},"rule_url":{"type":"string"},"url":{"type":"string"},"what":{"type":"string"}},"type":"object"},"type":"array"},"cloaking":{"description":"cloaking","type":"boolean"},"linkify_words":{"description":"linkify_words","type":"string"},"og_description":{"description":"og_description","type":"string"},"body_tags":{"description":"body_tags","type":"string"},"spam":{"description":"spam","type":"boolean"},"og_title":{"description":"og_title","type":"string"},"note":{"description":"note","type":"string"},"name":{"description":"name","type":"string"},"id":{"description":"Link ID. Required to update an existing link","type":"integer"},"gtm_id":{"description":"gtm_id","type":"string"},"og_image":{"description":"og_image","type":"string"},"block_bots":{"description":"block_bots","type":"boolean"},"utm_content":{"description":"utm_content","type":"string"},"enabled":{"description":"enabled","type":"boolean"},"url":{"description":"URL. Required to create a new link.","example":"www.somelink.com","format":"uri","type":"string"},"replacements":{"description":"replacements","type":"string"},"deleted":{"description":"deleted","type":"boolean"},"expiry_clicks":{"description":"Expire the link after this many clicks; visitors are then sent to `expiry_destination`.","example":1000,"type":"integer"},"workspace_id":{"description":"Workspace ID","type":"integer"},"utm_source":{"description":"utm_source","type":"string"},"slug":{"description":"slug","type":"string"},"domain":{"description":"domain","type":"string"},"forward_params":{"description":"forward_params","type":"boolean"},"utm_medium":{"description":"utm_medium","type":"string"},"head_tags":{"description":"head_tags","type":"string"},"ga4_tag_id":{"description":"ga4_tag_id","type":"string"},"utm_term":{"description":"utm_term","type":"string"},"utm_campaign":{"description":"utm_campaign","type":"string"}},"title":"LinkCreateOrUpdateRequest","type":"object"},"maxItems":1000,"title":"LinkBulkRequest","type":"array"}}},"description":"Links","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"description":"One result per submitted link, in request order.","items":{"properties":{"error":{"description":"Error detail (present when status is error)","type":"object"},"index":{"description":"0-based position in the request array","type":"integer"},"link":{"description":"The created or updated link (present when status is success)","type":"object"},"status":{"enum":["success","error"],"type":"string"}},"type":"object"},"title":"LinkBulkResult","type":"array"}}},"description":"Results"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"}},"security":[{"apiKey":[]},{"bearerAuth":[]}],"summary":"Create or update multiple links","tags":["Links"]}},"/api/v1/workspace/{workspace_id}/clicks":{"get":{"callbacks":{},"deprecated":false,"description":"Retrieve click analytics for a workspace. Filter by link, date range, country, and more. Returns time-series data suitable for charting.","operationId":"getClicks","parameters":[{"description":"The id of the Workspace","example":"42","in":"path","name":"workspace_id","required":true,"schema":{"type":"string"}},{"description":"The id of a single Link","example":"24","in":"query","name":"link_id","required":false,"schema":{"type":"string"}},{"description":"Filter clicks by multiple links. Provide a hyphen-separated list of link IDs.","example":"24-25-26","in":"query","name":"link_ids","required":false,"schema":{"type":"string"}},{"description":"The start date for the date range (format: YYYY-MM-DD or YYYY-MM-DDTHH:MM:SSZ)","in":"query","name":"start","required":false,"schema":{"type":"string"}},{"description":"The end date for the date range (format: YYYY-MM-DD or YYYY-MM-DDTHH:MM:SSZ)","in":"query","name":"end","required":false,"schema":{"type":"string"}},{"description":"Filter clicks by country using ISO 3166-1 alpha-2 country code e.g US","in":"query","name":"country","required":false,"schema":{"type":"string"}},{"description":"Filter clicks by browser name e.g Chrome, Firefox, Safari","in":"query","name":"browser","required":false,"schema":{"type":"string"}},{"description":"Filter clicks by platform/operating system e.g Windows, Mac, iOS, Android","in":"query","name":"platform","required":false,"schema":{"type":"string"}},{"description":"Filter clicks by referrer domain","in":"query","name":"referer","required":false,"schema":{"type":"string"}},{"description":"Filter clicks by Internet Service Provider name","in":"query","name":"isp","required":false,"schema":{"type":"string"}},{"description":"Set to false to exclude bot clicks from the results","example":"false","in":"query","name":"bots","required":false,"schema":{"type":"boolean"}},{"description":"Set to true to only include unique clicks in the results","example":"false","in":"query","name":"unique","required":false,"schema":{"type":"boolean"}},{"description":"Specify the format of the response. Available options are 'json' (default), 'csv', or 'tsv'.","example":"json","in":"query","name":"format","required":false,"schema":{"default":"json","enum":["json","csv","tsv"],"type":"string"}},{"description":"Return data as a matrix. When pivot=link_id, returns dates as rows and links as columns. CSV/TSV includes header rows for name, full_url, and id.","example":"link_id","in":"query","name":"pivot","required":false,"schema":{"enum":["link_id"],"type":"string"}},{"description":"The timezone to use for date/time calculations","example":"America/New_York","in":"query","name":"timezone","required":false,"schema":{"type":"string"}},{"description":"The frequency of data points in the response. Available options are 'day' (default) or 'hour'.","in":"query","name":"frequency","required":false,"schema":{"default":"day","enum":["day","hour"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"description":"Response schema for Clicks","example":{"traffic":[{"t":"2026-06-01","y":12},{"t":"2026-06-02","y":8},{"t":"2026-06-03","y":21}]},"properties":{"traffic":{"items":{"description":"Response schema for Click","properties":{"t":{"description":"Start of the bucket. `YYYY-MM-DD` when `frequency=day`; `YYYY-MM-DDTHH:MM:SS` when `frequency=hour`.","example":"2026-06-01","type":"string"},"y":{"description":"Click count for the bucket.","nullable":true,"type":"integer"}},"title":"ClickResponse","type":"object"},"type":"array"}},"title":"ClicksResponse","type":"object"}}},"description":"Click"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad Request"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"}},"security":[{"apiKey":[]}],"summary":"Get click analytics","tags":["Clicks"]}},"/api/v1/workspace/{workspace_id}/clicks/counters/{counter}":{"get":{"callbacks":{},"deprecated":false,"description":"Retrieve click analytics grouped by a specific dimension (counter). Returns aggregated counts for each unique value of the selected dimension, ordered by count descending.\n\n**A maximum of 10,000 values are returned.** High-cardinality dimensions (`destination`, `referer`, `remote_ip`, `isp`) can have far more distinct values than this on a busy workspace, in which case `values` contains only the top 10,000 by click count.\n\n`total` is always the total clicks across *every* group, not just the returned ones — so when the result is truncated, the sum of `count` in `values` will be less than `total`. Percentages calculated as `count / total` remain accurate.","operationId":"getClickCounters","parameters":[{"description":"The id of the Workspace","example":"42","in":"path","name":"workspace_id","required":true,"schema":{"type":"string"}},{"description":"The dimension to group clicks by. Options: country, city, region, platform, destination, referer, bot_name, isp, link_id, remote_ip, top_params, ad_network, and the UTM dimensions utm_source, utm_medium, utm_campaign, utm_content, utm_term. Any other value returns 400. For `link_id` each `value` is the full Link object rather than a string; for `top_params` each item also carries a `key` (the parameter name).","in":"path","name":"counter","required":true,"schema":{"enum":["country","city","region","platform","destination","referer","bot_name","isp","link_id","remote_ip","top_params","ad_network","utm_source","utm_medium","utm_campaign","utm_content","utm_term"],"type":"string"}},{"description":"The id of a single Link","example":"24","in":"query","name":"link_id","required":false,"schema":{"type":"string"}},{"description":"Hyphen-separated list of Link IDs","example":"24-25-26","in":"query","name":"link_ids","required":false,"schema":{"type":"string"}},{"description":"The start date for the date range (format: YYYY-MM-DD)","in":"query","name":"start","required":false,"schema":{"type":"string"}},{"description":"The end date for the date range (format: YYYY-MM-DD)","in":"query","name":"end","required":false,"schema":{"type":"string"}},{"description":"Filter by country using ISO 3166-1 alpha-2 country code","in":"query","name":"country","required":false,"schema":{"type":"string"}},{"description":"Set to false to exclude bot clicks from the results","example":"false","in":"query","name":"bots","required":false,"schema":{"type":"boolean"}},{"description":"Set to true to only count unique clicks","example":"false","in":"query","name":"unique","required":false,"schema":{"type":"boolean"}},{"description":"Specify the format of the response. Available options are 'json' (default), 'csv', or 'tsv'.","example":"json","in":"query","name":"format","required":false,"schema":{"default":"json","enum":["json","csv","tsv"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"description":"Response schema for Counters","example":{"total":215,"values":[{"count":120,"value":"US"},{"count":64,"value":"GB"},{"count":31,"value":"DE"}]},"properties":{"total":{"description":"Total clicks across all groups, including any not returned in `values`. When the result is truncated this is greater than the sum of `count` in `values`, so `count / total` still gives an accurate percentage.","type":"integer"},"values":{"description":"Grouped counts, ordered by count descending. Truncated to the top 10,000 values; if the dimension has more distinct values than that, the rest are not returned.","items":{"properties":{"count":{"type":"integer"},"key":{"description":"Only present for `counter=top_params`: the query-parameter name that `value` was seen on.","type":"string"},"value":{"description":"The grouped value. A string for every counter except `link_id`, which returns the full Link object; null when the dimension was not recorded for those clicks.","nullable":true,"oneOf":[{"type":"string"},{"$ref":"#/components/schemas/Link"}]}},"type":"object"},"maxItems":10000,"type":"array"}},"title":"CountersResponse","type":"object"}}},"description":"CounterResponse"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad Request"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"},"429":{"content":{"application/json":{"schema":{"description":"Rate limit exceeded error","properties":{"current_usage":{"type":"integer"},"error":{"type":"string"},"limit":{"type":"integer"},"message":{"type":"string"}},"title":"RateLimitError","type":"object"}}},"description":"Rate Limit Exceeded"}},"security":[{"apiKey":[]}],"summary":"Get click counts grouped by dimension","tags":["Clicks"]}},"/api/v1/workspace/{workspace_id}/domains":{"get":{"callbacks":{},"deprecated":false,"description":"Get all custom domains configured for a workspace. These domains can be used when creating short links.","operationId":"listDomains","parameters":[{"description":"The id of the Workspace","example":"42","in":"path","name":"workspace_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"description":"List of custom domains configured for a workspace.","example":{"domains":[{"name":"go.yourcompany.com"},{"name":"links.example.com"}]},"properties":{"domains":{"items":{"description":"A custom domain in a workspace.","properties":{"name":{"nullable":true,"type":"string"}},"title":"DomainListItem","type":"object"},"type":"array"}},"title":"DomainListResponse","type":"object"}}},"description":"Domain"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"}},"security":[{"apiKey":[]}],"summary":"List domains","tags":["Domains"]},"post":{"callbacks":{},"deprecated":false,"description":"Add a new custom domain to a specific workspace. You must configure a CNAME DNS record pointing to domains.linklyhq.com before adding the domain.","operationId":"createDomainInWorkspace","parameters":[{"description":"The id of the Workspace","example":"42","in":"path","name":"workspace_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"name":{"description":"Domain name (e.g., links.example.com)","type":"string"}},"required":["name"],"title":"CreateDomainRequest","type":"object"}},"application/x-www-form-urlencoded":{"schema":{"properties":{"name":{"description":"Domain name (e.g., links.example.com)","type":"string"}},"required":["name"],"title":"CreateDomainRequest","type":"object"}},"multipart/form-data":{"schema":{"properties":{"name":{"description":"Domain name (e.g., links.example.com)","type":"string"}},"required":["name"],"title":"CreateDomainRequest","type":"object"}}},"description":"Parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Domain"}}},"description":"Domain"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"}},"security":[{"apiKey":[]}],"summary":"Create domain in workspace","tags":["Domains"]}},"/api/v1/workspace/{workspace_id}/domains/{domain_id}":{"delete":{"callbacks":{},"deprecated":false,"description":"Remove a custom domain from your workspace. Links using this domain will no longer work.","operationId":"deleteDomain","parameters":[{"description":"The id of the Workspace","example":"42","in":"path","name":"workspace_id","required":true,"schema":{"type":"string"}},{"description":"The id of the Domain","example":"103","in":"path","name":"domain_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"example":"Domain deleted.","type":"string"}}},"description":"DomainDeleted"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"}},"security":[{"apiKey":[]}],"summary":"Delete a domain","tags":["Domains"]}},"/api/v1/workspace/{workspace_id}/domains/{id}/favicon":{"patch":{"callbacks":{},"deprecated":false,"description":"Update the favicon URL for a custom domain.","operationId":"updateDomainFavicon","parameters":[{"description":"The id of the Workspace","example":"42","in":"path","name":"workspace_id","required":true,"schema":{"type":"string"}},{"description":"The id of the Domain","example":"103","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"favicon_url":{"description":"URL to favicon image","format":"uri","type":"string"}},"title":"UpdateFaviconRequest","type":"object"}},"application/x-www-form-urlencoded":{"schema":{"properties":{"favicon_url":{"description":"URL to favicon image","format":"uri","type":"string"}},"title":"UpdateFaviconRequest","type":"object"}},"multipart/form-data":{"schema":{"properties":{"favicon_url":{"description":"URL to favicon image","format":"uri","type":"string"}},"title":"UpdateFaviconRequest","type":"object"}}},"description":"Parameters","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"favicon_url":{"nullable":true,"type":"string"},"id":{"type":"integer"},"name":{"type":"string"}},"type":"object"}}},"description":"Domain"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"}},"security":[{"apiKey":[]}],"summary":"Update domain favicon","tags":["Domains"]}},"/api/v1/workspace/{workspace_id}/links":{"delete":{"callbacks":{},"deprecated":false,"description":"Delete one or more links by their IDs. Deleted links are moved to the workspace's trash and can be restored with restoreLinks.","operationId":"deleteLinks","parameters":[{"description":"The id of the Workspace","example":"42","in":"path","name":"workspace_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"description":"Delete body to delete links","properties":{"ids":{"items":{"type":"integer"},"type":"array"}},"title":"DeleteLinksRequest","type":"object"}},"application/x-www-form-urlencoded":{"schema":{"description":"Delete body to delete links","properties":{"ids":{"items":{"type":"integer"},"type":"array"}},"title":"DeleteLinksRequest","type":"object"}},"multipart/form-data":{"schema":{"description":"Delete body to delete links","properties":{"ids":{"items":{"type":"integer"},"type":"array"}},"title":"DeleteLinksRequest","type":"object"}}},"description":"Parameters","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"example":"Links deleted.","type":"string"}}},"description":"LinksDeleted"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"}},"security":[{"apiKey":[]}],"summary":"Delete links","tags":["Links"]},"post":{"callbacks":{},"deprecated":false,"description":"Create a new link or update an existing one. Include an 'id' field to update an existing link. Can also accept an array of links for batch operations.","operationId":"createOrUpdateWorkspaceLink","parameters":[{"description":"The id of the Workspace","example":"42","in":"path","name":"workspace_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"description":"Request body for creating or updating a link","properties":{"fb_pixel_id":{"description":"Facebook Pixel ID","nullable":true,"type":"string"},"tiktok_pixel_id":{"description":"TikTok Pixel ID","nullable":true,"type":"string"},"hide_referrer":{"description":"Hide referrer from destination","type":"boolean"},"expiry_datetime":{"description":"Link expiration date/time","format":"date-time","nullable":true,"type":"string"},"expiry_destination":{"description":"Redirect URL after expiry","nullable":true,"type":"string"},"rules":{"description":"Redirect rules","items":{"$ref":"#/components/schemas/Rule"},"type":"array"},"domain_id":{"description":"Domain ID (alternative to domain name)","type":"integer"},"cloaking":{"description":"Enable link cloaking","type":"boolean"},"linkify_words":{"description":"Words to linkify","nullable":true,"type":"string"},"sticky_rotator":{"description":"Rotator links only: send a returning visitor to the same destination as last time, remembered in a cookie for 30 days. Not available on privacy-mode links; turning privacy mode on switches it off.","type":"boolean"},"og_description":{"description":"Open Graph description","nullable":true,"type":"string"},"skip_social_crawler_tracking":{"description":"Skip tracking social media crawlers","type":"boolean"},"body_tags":{"description":"Custom HTML tags for body","nullable":true,"type":"string"},"og_title":{"description":"Open Graph title","nullable":true,"type":"string"},"note":{"description":"Private note about this link","nullable":true,"type":"string"},"name":{"description":"Nickname for the link","nullable":true,"type":"string"},"id":{"description":"Link ID (include to update existing link)","type":"integer"},"gtm_id":{"description":"Google Tag Manager ID","nullable":true,"type":"string"},"og_image":{"description":"Open Graph image URL","nullable":true,"type":"string"},"block_bots":{"description":"Block bot traffic","type":"boolean"},"utm_content":{"nullable":true,"type":"string"},"enabled":{"description":"Whether the link is active","type":"boolean"},"privacy_mode":{"description":"Record clicks without personal data (no IP, location, network, user agent, referrer or query parameters; click times kept to the hour). Turning it on also clears tracking pixels, custom scripts, conversion tracking, webhooks and click notifications on the link, and click webhooks stop firing for it. Paid plans only.","type":"boolean"},"url":{"description":"The destination URL","format":"uri","type":"string"},"replacements":{"description":"URL parameter replacements","nullable":true,"type":"string"},"qr_styles":{"description":"QR code styling options","nullable":true,"type":"object"},"webhooks":{"description":"Webhook URLs","items":{"type":"string"},"type":"array"},"expiry_clicks":{"description":"Expire link after this many clicks","nullable":true,"type":"integer"},"public_analytics":{"description":"Make analytics publicly accessible","type":"boolean"},"utm_source":{"nullable":true,"type":"string"},"slug":{"description":"Custom slug (must start with /)","nullable":true,"type":"string"},"domain":{"description":"Custom domain (without trailing /)","nullable":true,"type":"string"},"forward_params":{"description":"Forward query parameters to destination","type":"boolean"},"utm_medium":{"nullable":true,"type":"string"},"head_tags":{"description":"Custom HTML tags for head","nullable":true,"type":"string"},"ga4_tag_id":{"description":"Google Analytics 4 Tag ID","nullable":true,"type":"string"},"utm_term":{"nullable":true,"type":"string"},"utm_campaign":{"nullable":true,"type":"string"}},"required":["url"],"title":"CreateOrUpdateLinkRequest","type":"object"}},"application/x-www-form-urlencoded":{"schema":{"description":"Request body for creating or updating a link","properties":{"fb_pixel_id":{"description":"Facebook Pixel ID","nullable":true,"type":"string"},"tiktok_pixel_id":{"description":"TikTok Pixel ID","nullable":true,"type":"string"},"hide_referrer":{"description":"Hide referrer from destination","type":"boolean"},"expiry_datetime":{"description":"Link expiration date/time","format":"date-time","nullable":true,"type":"string"},"expiry_destination":{"description":"Redirect URL after expiry","nullable":true,"type":"string"},"rules":{"description":"Redirect rules","items":{"$ref":"#/components/schemas/Rule"},"type":"array"},"domain_id":{"description":"Domain ID (alternative to domain name)","type":"integer"},"cloaking":{"description":"Enable link cloaking","type":"boolean"},"linkify_words":{"description":"Words to linkify","nullable":true,"type":"string"},"sticky_rotator":{"description":"Rotator links only: send a returning visitor to the same destination as last time, remembered in a cookie for 30 days. Not available on privacy-mode links; turning privacy mode on switches it off.","type":"boolean"},"og_description":{"description":"Open Graph description","nullable":true,"type":"string"},"skip_social_crawler_tracking":{"description":"Skip tracking social media crawlers","type":"boolean"},"body_tags":{"description":"Custom HTML tags for body","nullable":true,"type":"string"},"og_title":{"description":"Open Graph title","nullable":true,"type":"string"},"note":{"description":"Private note about this link","nullable":true,"type":"string"},"name":{"description":"Nickname for the link","nullable":true,"type":"string"},"id":{"description":"Link ID (include to update existing link)","type":"integer"},"gtm_id":{"description":"Google Tag Manager ID","nullable":true,"type":"string"},"og_image":{"description":"Open Graph image URL","nullable":true,"type":"string"},"block_bots":{"description":"Block bot traffic","type":"boolean"},"utm_content":{"nullable":true,"type":"string"},"enabled":{"description":"Whether the link is active","type":"boolean"},"privacy_mode":{"description":"Record clicks without personal data (no IP, location, network, user agent, referrer or query parameters; click times kept to the hour). Turning it on also clears tracking pixels, custom scripts, conversion tracking, webhooks and click notifications on the link, and click webhooks stop firing for it. Paid plans only.","type":"boolean"},"url":{"description":"The destination URL","format":"uri","type":"string"},"replacements":{"description":"URL parameter replacements","nullable":true,"type":"string"},"qr_styles":{"description":"QR code styling options","nullable":true,"type":"object"},"webhooks":{"description":"Webhook URLs","items":{"type":"string"},"type":"array"},"expiry_clicks":{"description":"Expire link after this many clicks","nullable":true,"type":"integer"},"public_analytics":{"description":"Make analytics publicly accessible","type":"boolean"},"utm_source":{"nullable":true,"type":"string"},"slug":{"description":"Custom slug (must start with /)","nullable":true,"type":"string"},"domain":{"description":"Custom domain (without trailing /)","nullable":true,"type":"string"},"forward_params":{"description":"Forward query parameters to destination","type":"boolean"},"utm_medium":{"nullable":true,"type":"string"},"head_tags":{"description":"Custom HTML tags for head","nullable":true,"type":"string"},"ga4_tag_id":{"description":"Google Analytics 4 Tag ID","nullable":true,"type":"string"},"utm_term":{"nullable":true,"type":"string"},"utm_campaign":{"nullable":true,"type":"string"}},"required":["url"],"title":"CreateOrUpdateLinkRequest","type":"object"}},"multipart/form-data":{"schema":{"description":"Request body for creating or updating a link","properties":{"fb_pixel_id":{"description":"Facebook Pixel ID","nullable":true,"type":"string"},"tiktok_pixel_id":{"description":"TikTok Pixel ID","nullable":true,"type":"string"},"hide_referrer":{"description":"Hide referrer from destination","type":"boolean"},"expiry_datetime":{"description":"Link expiration date/time","format":"date-time","nullable":true,"type":"string"},"expiry_destination":{"description":"Redirect URL after expiry","nullable":true,"type":"string"},"rules":{"description":"Redirect rules","items":{"$ref":"#/components/schemas/Rule"},"type":"array"},"domain_id":{"description":"Domain ID (alternative to domain name)","type":"integer"},"cloaking":{"description":"Enable link cloaking","type":"boolean"},"linkify_words":{"description":"Words to linkify","nullable":true,"type":"string"},"sticky_rotator":{"description":"Rotator links only: send a returning visitor to the same destination as last time, remembered in a cookie for 30 days. Not available on privacy-mode links; turning privacy mode on switches it off.","type":"boolean"},"og_description":{"description":"Open Graph description","nullable":true,"type":"string"},"skip_social_crawler_tracking":{"description":"Skip tracking social media crawlers","type":"boolean"},"body_tags":{"description":"Custom HTML tags for body","nullable":true,"type":"string"},"og_title":{"description":"Open Graph title","nullable":true,"type":"string"},"note":{"description":"Private note about this link","nullable":true,"type":"string"},"name":{"description":"Nickname for the link","nullable":true,"type":"string"},"id":{"description":"Link ID (include to update existing link)","type":"integer"},"gtm_id":{"description":"Google Tag Manager ID","nullable":true,"type":"string"},"og_image":{"description":"Open Graph image URL","nullable":true,"type":"string"},"block_bots":{"description":"Block bot traffic","type":"boolean"},"utm_content":{"nullable":true,"type":"string"},"enabled":{"description":"Whether the link is active","type":"boolean"},"privacy_mode":{"description":"Record clicks without personal data (no IP, location, network, user agent, referrer or query parameters; click times kept to the hour). Turning it on also clears tracking pixels, custom scripts, conversion tracking, webhooks and click notifications on the link, and click webhooks stop firing for it. Paid plans only.","type":"boolean"},"url":{"description":"The destination URL","format":"uri","type":"string"},"replacements":{"description":"URL parameter replacements","nullable":true,"type":"string"},"qr_styles":{"description":"QR code styling options","nullable":true,"type":"object"},"webhooks":{"description":"Webhook URLs","items":{"type":"string"},"type":"array"},"expiry_clicks":{"description":"Expire link after this many clicks","nullable":true,"type":"integer"},"public_analytics":{"description":"Make analytics publicly accessible","type":"boolean"},"utm_source":{"nullable":true,"type":"string"},"slug":{"description":"Custom slug (must start with /)","nullable":true,"type":"string"},"domain":{"description":"Custom domain (without trailing /)","nullable":true,"type":"string"},"forward_params":{"description":"Forward query parameters to destination","type":"boolean"},"utm_medium":{"nullable":true,"type":"string"},"head_tags":{"description":"Custom HTML tags for head","nullable":true,"type":"string"},"ga4_tag_id":{"description":"Google Analytics 4 Tag ID","nullable":true,"type":"string"},"utm_term":{"nullable":true,"type":"string"},"utm_campaign":{"nullable":true,"type":"string"}},"required":["url"],"title":"CreateOrUpdateLinkRequest","type":"object"}}},"description":"Link","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"description":"A link with click statistics, as returned by workspace link endpoints.","properties":{"fb_pixel_id":{"nullable":true,"type":"string"},"human_clicks_total":{"description":"Lifetime clicks with no bot signal — the subset of `clicks_total` where neither a bot user-agent nor a verified-bot category was detected. Recorded from 2019 onward.","type":"integer"},"sparkline":{"description":"Daily human clicks over the last 30 days, oldest first.","items":{"type":"integer"},"type":"array"},"clicks_thirty_days":{"description":"Clicks in the last 30 days, including bot traffic.","type":"integer"},"tiktok_pixel_id":{"nullable":true,"type":"string"},"hide_referrer":{"nullable":true,"type":"boolean"},"rules":{"items":{"$ref":"#/components/schemas/Rule"},"nullable":true,"type":"array"},"cloaking":{"nullable":true,"type":"boolean"},"linkify_words":{"nullable":true,"type":"string"},"full_url":{"format":"uri","type":"string"},"clicks_today":{"description":"Clicks so far today (UTC), including bot traffic.","type":"integer"},"og_description":{"nullable":true,"type":"string"},"body_tags":{"nullable":true,"type":"string"},"og_title":{"nullable":true,"type":"string"},"note":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"id":{"nullable":true,"type":"integer"},"gtm_id":{"nullable":true,"type":"string"},"og_image":{"nullable":true,"type":"string"},"block_bots":{"nullable":true,"type":"boolean"},"clicks_total":{"description":"Lifetime clicks, including bot traffic.","type":"integer"},"human_clicks_thirty_days":{"description":"Clicks in the last 30 days with no bot signal — the subset of `clicks_thirty_days`.","type":"integer"},"utm_content":{"nullable":true,"type":"string"},"human_clicks_today":{"description":"Clicks so far today (UTC) with no bot signal.","type":"integer"},"enabled":{"nullable":true,"type":"boolean"},"url":{"format":"uri","type":"string"},"replacements":{"nullable":true,"type":"string"},"deleted":{"nullable":true,"type":"boolean"},"workspace_id":{"nullable":true,"type":"integer"},"public_analytics":{"nullable":true,"type":"boolean"},"utm_source":{"nullable":true,"type":"string"},"slug":{"nullable":true,"type":"string"},"domain":{"nullable":true,"type":"string"},"forward_params":{"nullable":true,"type":"boolean"},"utm_medium":{"nullable":true,"type":"string"},"head_tags":{"nullable":true,"type":"string"},"ga4_tag_id":{"nullable":true,"type":"string"},"utm_term":{"nullable":true,"type":"string"},"utm_campaign":{"nullable":true,"type":"string"},"human_clicks_previous_day":{"description":"Clicks yesterday (UTC) with no bot signal.","type":"integer"}},"title":"WorkspaceLink","type":"object"}}},"description":"Link"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"}},"security":[{"apiKey":[]}],"summary":"Create or update a link","tags":["Links"]}},"/api/v1/workspace/{workspace_id}/links/export":{"get":{"callbacks":{},"deprecated":false,"description":"Export all links in a workspace as JSON or CSV.","operationId":"exportLinks","parameters":[{"description":"The id of the Workspace","example":"42","in":"path","name":"workspace_id","required":true,"schema":{"type":"string"}},{"description":"Export format","example":"json","in":"query","name":"format","required":false,"schema":{"default":"json","enum":["json","csv"],"type":"string"}},{"description":"Search query to filter links","example":"campaign","in":"query","name":"search","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"items":{"description":"A link with click statistics, as returned by workspace link endpoints.","properties":{"fb_pixel_id":{"nullable":true,"type":"string"},"human_clicks_total":{"description":"Lifetime clicks with no bot signal — the subset of `clicks_total` where neither a bot user-agent nor a verified-bot category was detected. Recorded from 2019 onward.","type":"integer"},"sparkline":{"description":"Daily human clicks over the last 30 days, oldest first.","items":{"type":"integer"},"type":"array"},"clicks_thirty_days":{"description":"Clicks in the last 30 days, including bot traffic.","type":"integer"},"tiktok_pixel_id":{"nullable":true,"type":"string"},"hide_referrer":{"nullable":true,"type":"boolean"},"rules":{"items":{"$ref":"#/components/schemas/Rule"},"nullable":true,"type":"array"},"cloaking":{"nullable":true,"type":"boolean"},"linkify_words":{"nullable":true,"type":"string"},"full_url":{"format":"uri","type":"string"},"clicks_today":{"description":"Clicks so far today (UTC), including bot traffic.","type":"integer"},"og_description":{"nullable":true,"type":"string"},"body_tags":{"nullable":true,"type":"string"},"og_title":{"nullable":true,"type":"string"},"note":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"id":{"nullable":true,"type":"integer"},"gtm_id":{"nullable":true,"type":"string"},"og_image":{"nullable":true,"type":"string"},"block_bots":{"nullable":true,"type":"boolean"},"clicks_total":{"description":"Lifetime clicks, including bot traffic.","type":"integer"},"human_clicks_thirty_days":{"description":"Clicks in the last 30 days with no bot signal — the subset of `clicks_thirty_days`.","type":"integer"},"utm_content":{"nullable":true,"type":"string"},"human_clicks_today":{"description":"Clicks so far today (UTC) with no bot signal.","type":"integer"},"enabled":{"nullable":true,"type":"boolean"},"url":{"format":"uri","type":"string"},"replacements":{"nullable":true,"type":"string"},"deleted":{"nullable":true,"type":"boolean"},"workspace_id":{"nullable":true,"type":"integer"},"public_analytics":{"nullable":true,"type":"boolean"},"utm_source":{"nullable":true,"type":"string"},"slug":{"nullable":true,"type":"string"},"domain":{"nullable":true,"type":"string"},"forward_params":{"nullable":true,"type":"boolean"},"utm_medium":{"nullable":true,"type":"string"},"head_tags":{"nullable":true,"type":"string"},"ga4_tag_id":{"nullable":true,"type":"string"},"utm_term":{"nullable":true,"type":"string"},"utm_campaign":{"nullable":true,"type":"string"},"human_clicks_previous_day":{"description":"Clicks yesterday (UTC) with no bot signal.","type":"integer"}},"title":"WorkspaceLink","type":"object"},"type":"array"}}},"description":"Links"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"}},"security":[{"apiKey":[]}],"summary":"Export links","tags":["Links"]}},"/api/v1/workspace/{workspace_id}/links/restore":{"post":{"callbacks":{},"deprecated":false,"description":"Restore one or more soft-deleted links by their IDs. Reconstructs each link's short URL (domain/slug) from its preserved full_url. Links whose short URL is now taken by a live link are skipped and reported under `conflicts`.","operationId":"restoreLinks","parameters":[{"description":"The id of the Workspace","example":"42","in":"path","name":"workspace_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"description":"Delete body to delete links","properties":{"ids":{"items":{"type":"integer"},"type":"array"}},"title":"DeleteLinksRequest","type":"object"}},"application/x-www-form-urlencoded":{"schema":{"description":"Delete body to delete links","properties":{"ids":{"items":{"type":"integer"},"type":"array"}},"title":"DeleteLinksRequest","type":"object"}},"multipart/form-data":{"schema":{"description":"Delete body to delete links","properties":{"ids":{"items":{"type":"integer"},"type":"array"}},"title":"DeleteLinksRequest","type":"object"}}},"description":"Parameters","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"conflicts":{"items":{"properties":{"domain":{"type":"string"},"id":{"type":"integer"},"slug":{"type":"string"}},"type":"object"},"type":"array"},"restored":{"example":500,"type":"integer"}},"type":"object"}}},"description":"LinksRestored"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"}},"security":[{"apiKey":[]}],"summary":"Restore links","tags":["Links"]}},"/api/v1/workspace/{workspace_id}/links/{id}":{"delete":{"callbacks":{},"deprecated":false,"description":"Delete a specific link by ID. The link is moved to the workspace's trash and can be restored with restoreLinks. Deleting a link that is already in the trash is a no-op and still returns 200; an id that does not exist in the workspace returns 404.","operationId":"deleteLink","parameters":[{"description":"The id of the Workspace","example":"42","in":"path","name":"workspace_id","required":true,"schema":{"type":"string"}},{"description":"The id of the Link","example":24,"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"example":"Link deleted.","type":"string"}}},"description":"LinkDeleted"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"}},"security":[{"apiKey":[]}],"summary":"Delete a single link","tags":["Links"]}},"/api/v1/workspace/{workspace_id}/list_links":{"get":{"callbacks":{},"deprecated":false,"description":"Get a paginated list of all links in a workspace. Supports search, sorting, and pagination. Returns link details including click statistics.","operationId":"listLinks","parameters":[{"description":"The id of the Workspace","example":"42","in":"path","name":"workspace_id","required":true,"schema":{"type":"string"}},{"description":"The search query","example":"test","in":"query","name":"search","required":false,"schema":{"type":"string"}},{"description":"Page","in":"query","name":"page","required":false,"schema":{"default":1,"type":"integer"}},{"description":"Number of links to return","in":"query","name":"page_size","required":false,"schema":{"default":1000,"type":"integer"}},{"description":"Sort by field. Accepts any link column, plus the computed click aggregates: `clicks_total`, `clicks_today`, `clicks_previous_day`, `clicks_thirty_days`, `human_clicks_total`, `human_clicks_thirty_days`, `human_clicks_today`, `human_clicks_previous_day`.","in":"query","name":"sort_by","required":false,"schema":{"type":"string"}},{"description":"Sort direction","in":"query","name":"sort_dir","required":false,"schema":{"items":{"enum":["desc","asc"],"type":"string"},"type":"string"}},{"description":"Filter links by exact field match. Composable — multiple filters are ANDed. e.g. filter[utm_campaign]=summer_sale&filter[utm_source]=newsletter","explode":true,"in":"query","name":"filter","required":false,"schema":{"additionalProperties":false,"properties":{"domain":{"type":"string"},"slug":{"type":"string"},"utm_campaign":{"type":"string"},"utm_content":{"type":"string"},"utm_medium":{"type":"string"},"utm_source":{"type":"string"},"utm_term":{"type":"string"}},"type":"object"},"style":"deepObject"},{"description":"Return soft-deleted (trashed) links instead of active ones","in":"query","name":"deleted","required":false,"schema":{"default":false,"type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"description":"Paginated list of links in a workspace, with click statistics.","example":{"links":[{"clicks_thirty_days":64,"clicks_today":3,"clicks_total":215,"domain":"go.yourcompany.com","enabled":true,"full_url":"https://go.yourcompany.com/promo","human_clicks_thirty_days":51,"human_clicks_today":2,"human_clicks_total":168,"id":30,"name":"Summer promo","slug":"/promo","sparkline":[0,2,5,1,8,3],"url":"https://www.example.com","workspace_id":42}],"page_number":1,"page_size":1000,"total_entries":1,"total_pages":1,"workspace_link_count":1},"properties":{"links":{"items":{"description":"A link with click statistics, as returned by workspace link endpoints.","properties":{"fb_pixel_id":{"nullable":true,"type":"string"},"human_clicks_total":{"description":"Lifetime clicks with no bot signal — the subset of `clicks_total` where neither a bot user-agent nor a verified-bot category was detected. Recorded from 2019 onward.","type":"integer"},"sparkline":{"description":"Daily human clicks over the last 30 days, oldest first.","items":{"type":"integer"},"type":"array"},"clicks_thirty_days":{"description":"Clicks in the last 30 days, including bot traffic.","type":"integer"},"tiktok_pixel_id":{"nullable":true,"type":"string"},"hide_referrer":{"nullable":true,"type":"boolean"},"rules":{"items":{"$ref":"#/components/schemas/Rule"},"nullable":true,"type":"array"},"cloaking":{"nullable":true,"type":"boolean"},"linkify_words":{"nullable":true,"type":"string"},"full_url":{"format":"uri","type":"string"},"clicks_today":{"description":"Clicks so far today (UTC), including bot traffic.","type":"integer"},"og_description":{"nullable":true,"type":"string"},"body_tags":{"nullable":true,"type":"string"},"og_title":{"nullable":true,"type":"string"},"note":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"id":{"nullable":true,"type":"integer"},"gtm_id":{"nullable":true,"type":"string"},"og_image":{"nullable":true,"type":"string"},"block_bots":{"nullable":true,"type":"boolean"},"clicks_total":{"description":"Lifetime clicks, including bot traffic.","type":"integer"},"human_clicks_thirty_days":{"description":"Clicks in the last 30 days with no bot signal — the subset of `clicks_thirty_days`.","type":"integer"},"utm_content":{"nullable":true,"type":"string"},"human_clicks_today":{"description":"Clicks so far today (UTC) with no bot signal.","type":"integer"},"enabled":{"nullable":true,"type":"boolean"},"url":{"format":"uri","type":"string"},"replacements":{"nullable":true,"type":"string"},"deleted":{"nullable":true,"type":"boolean"},"workspace_id":{"nullable":true,"type":"integer"},"public_analytics":{"nullable":true,"type":"boolean"},"utm_source":{"nullable":true,"type":"string"},"slug":{"nullable":true,"type":"string"},"domain":{"nullable":true,"type":"string"},"forward_params":{"nullable":true,"type":"boolean"},"utm_medium":{"nullable":true,"type":"string"},"head_tags":{"nullable":true,"type":"string"},"ga4_tag_id":{"nullable":true,"type":"string"},"utm_term":{"nullable":true,"type":"string"},"utm_campaign":{"nullable":true,"type":"string"},"human_clicks_previous_day":{"description":"Clicks yesterday (UTC) with no bot signal.","type":"integer"}},"title":"WorkspaceLink","type":"object"},"type":"array"},"page_number":{"type":"integer"},"page_size":{"type":"integer"},"total_entries":{"type":"integer"},"total_pages":{"type":"integer"},"total_rows":{"type":"integer"},"workspace_link_count":{"type":"integer"}},"title":"LinkListResponse","type":"object"}}},"description":"Link"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Error"}},"security":[{"apiKey":[]}],"summary":"List links","tags":["Links"]}},"/api/v1/workspace/{workspace_id}/webhooks":{"get":{"callbacks":{},"deprecated":false,"description":"Get all webhook subscriptions for a specific workspace.","operationId":"listWorkspaceWebhooks","parameters":[{"description":"The ID of the workspace","example":42,"in":"path","name":"workspace_id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"description":"List of webhook subscriptions","items":{"properties":{"id":{"description":"The webhook URL","example":"https://hooks.zapier.com/hooks/catch/123456/abcdef/","type":"string"}},"type":"object"},"title":"WebhooksListResponse","type":"array"}}},"description":"Webhook list"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"}},"security":[{"apiKey":[]}],"summary":"List webhooks for a workspace","tags":["Webhooks"]},"post":{"callbacks":{},"deprecated":false,"description":"Subscribe a webhook URL to receive events for every link in the workspace. A new subscription receives a `POST` for each `click`, `link.created`, `link.updated`, and `link.deleted`; the events can be narrowed per URL in the workspace settings. Branch on the JSON `event` field; see the Webhooks section for payload shapes.","operationId":"subscribeWebhookToWorkspace","parameters":[{"description":"The ID of the workspace to subscribe to","example":42,"in":"path","name":"workspace_id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"description":"Request body for subscribing a webhook","properties":{"url":{"description":"The webhook URL to receive click notifications","example":"https://hooks.zapier.com/hooks/catch/123456/abcdef/","format":"uri","type":"string"}},"required":["url"],"title":"WebhookSubscribeRequest","type":"object"}},"application/x-www-form-urlencoded":{"schema":{"description":"Request body for subscribing a webhook","properties":{"url":{"description":"The webhook URL to receive click notifications","example":"https://hooks.zapier.com/hooks/catch/123456/abcdef/","format":"uri","type":"string"}},"required":["url"],"title":"WebhookSubscribeRequest","type":"object"}},"multipart/form-data":{"schema":{"description":"Request body for subscribing a webhook","properties":{"url":{"description":"The webhook URL to receive click notifications","example":"https://hooks.zapier.com/hooks/catch/123456/abcdef/","format":"uri","type":"string"}},"required":["url"],"title":"WebhookSubscribeRequest","type":"object"}}},"description":"Webhook subscription","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"description":"Response after subscribing a webhook","properties":{"id":{"description":"The webhook URL (used as the hook ID for unsubscribing)","example":"https://hooks.zapier.com/hooks/catch/123456/abcdef/","type":"string"}},"title":"WebhookSubscribeResponse","type":"object"}}},"description":"Webhook subscribed"},"400":{"content":{"application/json":{"schema":{"description":"Error response","properties":{"error":{"example":"Missing or invalid parameters","type":"string"}},"title":"WebhookErrorResponse","type":"object"}}},"description":"Bad request"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"}},"security":[{"apiKey":[]}],"summary":"Subscribe webhook to a workspace","tags":["Webhooks"]}},"/api/v1/workspace/{workspace_id}/webhooks/{hook_id}":{"delete":{"callbacks":{},"deprecated":false,"description":"Remove a webhook subscription from a workspace. The hook_id is the URL-encoded webhook URL.","operationId":"unsubscribeWebhookFromWorkspace","parameters":[{"description":"The ID of the workspace","example":42,"in":"path","name":"workspace_id","required":true,"schema":{"type":"integer"}},{"description":"The webhook URL (URL-encoded)","example":"https%3A%2F%2Fhooks.example.com%2Fabc123","in":"path","name":"hook_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"string"}}},"description":"Webhook unsubscribed"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Forbidden"}},"security":[{"apiKey":[]}],"summary":"Unsubscribe webhook from a workspace","tags":["Webhooks"]}},"/api/v1/workspaces":{"get":{"callbacks":{},"deprecated":false,"description":"Returns a list of all workspaces the authenticated user has access to. Use this to discover available workspace IDs for other API calls.","operationId":"listWorkspaces","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"example":[{"id":123,"name":"My Workspace"},{"id":456,"name":"Another Workspace"}],"items":{"properties":{"id":{"description":"Workspace ID","type":"integer"},"name":{"description":"Workspace name","type":"string"}},"type":"object"},"type":"array"}}},"description":"Workspaces"},"401":{"content":{"text/plain":{"schema":{"example":"Not authorized","title":"NotAuthorized","type":"string"}}},"description":"Unauthorized"}},"security":[{"apiKey":[]},{"bearerAuth":[]}],"summary":"List user workspaces","tags":["Workspaces"]}}},"security":[{"bearerAuth":[]},{"apiKey":[]},{"basicAuth":[]}],"servers":[{"url":"https://api.linklyhq.com","variables":{}}],"tags":[{"description":"Create, retrieve, update, and delete short links. Links can have custom slugs, UTM parameters, retargeting pixels, redirect rules, expiry conditions, and more.","name":"Links"},{"description":"Manage custom domains for your workspace. Custom domains let you brand your short links (e.g. `go.yourcompany.com`). You must configure a CNAME DNS record pointing to `domains.linklyhq.com` before adding a domain.","name":"Domains"},{"description":"List the workspaces your API key has access to. Workspace IDs are required by most other endpoints.","name":"Workspaces"},{"description":"Subscribe to real-time events via webhooks. A webhook can be attached to an individual link or to an entire workspace, and Linkly sends a `POST` request to your endpoint when a matching event occurs.\n\nA **link** subscription receives events for that one link. A **workspace** subscription receives events for every link in the workspace — this is how you receive `link.created` for newly created links.\n\nDelivery is fire-and-forget with a 5-second timeout and no retries, so your endpoint should respond quickly with a `2xx` status.\n\n### Event types\n\nLink subscriptions, and workspace subscriptions created through this API, receive every event type. A workspace webhook can be limited to chosen events in the workspace settings. Branch on the top-level `event` field:\n\n| `event` | Sent when |\n| --- | --- |\n| `click` | A short link is clicked. The body includes a `click` object with the request metadata. |\n| `link.created` | A new link is created. |\n| `link.updated` | A link is changed. Fires on every update, including partial/autosaved edits, so expect several per editing session. |\n| `link.deleted` | A link is deleted. The `link` object keeps the `slug`/`domain` it had before deletion. |\n\n### Click payload\n\nEach request body is a JSON object shaped like this:\n\n```json\n{\n  \"event\": \"click\",\n  \"timestamp\": \"2026-06-09T12:34:56.000000Z\",\n  \"link\": {\n    \"id\": 30,\n    \"url\": \"https://www.example.com\",\n    \"full_url\": \"https://go.yourcompany.com/promo\",\n    \"slug\": \"/promo\",\n    \"workspace_id\": 42,\n    \"destination\": \"https://www.example.com?utm_source=newsletter\",\n    \"rules\": []\n  },\n  \"click\": {\n    \"browser_name\": \"Chrome\",\n    \"platform\": \"Mac\",\n    \"destination\": \"https://www.example.com?utm_source=newsletter\",\n    \"country\": \"US\",\n    \"referer\": \"https://twitter.com/\",\n    \"user_agent\": \"Mozilla/5.0 ...\",\n    \"accept_language\": \"en-US\",\n    \"bot_name\": null,\n    \"params\": {}\n  }\n}\n```\n\nThe `link` object contains the link's configuration (the same fields as the Link schema, plus the resolved `destination`). The `click` object contains the request metadata: `browser_name`, `platform`, `destination`, `referer`, `user_agent`, `accept_language`, `bot_name`, the geo fields (`country`, `city`, `region`, `isp`, …), the `sec_fetch_*` headers, and any forwarded query `params`.\n\n### Link lifecycle payload\n\n`link.created`, `link.updated`, and `link.deleted` share one shape. There is no `click` object — the `link` object is the full link record, including `inserted_at` / `updated_at`:\n\n```json\n{\n  \"event\": \"link.created\",\n  \"timestamp\": \"2026-06-20T12:34:56.000000Z\",\n  \"link\": {\n    \"id\": 30,\n    \"url\": \"https://www.example.com\",\n    \"full_url\": \"https://go.yourcompany.com/promo\",\n    \"slug\": \"/promo\",\n    \"domain\": \"go.yourcompany.com\",\n    \"workspace_id\": 42,\n    \"name\": \"Summer promo\",\n    \"enabled\": true,\n    \"inserted_at\": \"2026-06-20T12:34:56Z\",\n    \"updated_at\": \"2026-06-20T12:34:56Z\",\n    \"rules\": []\n  }\n}\n```\n","name":"Webhooks"},{"description":"Query click analytics for your workspace. Filter by link, date range, country, browser, platform, referrer, and more. Supports time-series and grouped (counter) responses in JSON, CSV, or TSV.","name":"Clicks"},{"description":"Report what happened *after* the click — purchases, signups, or any custom event on your own site — and attribute it back to the link that drove it.\n\nAttribution runs on a `linkly_cid` token. When conversion tracking is enabled, Linkly appends it to the destination URL on redirect; your landing page stores it, and you hand it back when the conversion happens.\n\nA conversion that cannot be attributed to a link — no `linkly_cid`, an unrecognised one, and no earlier attributed event for the same `external_id` — is **discarded**, not recorded. The request is answered with `202` and `attributed: false` so you can tell a token that never arrives apart from a genuine sale. Linkly is not the system of record for your revenue; it only keeps conversions it can tie to a link.\n\nSupply an `event_id` to make reporting idempotent: repeating the same one returns the original conversion rather than double-counting it.\n\nWhen authenticating with an API key, pass `workspace_id` as a query parameter. OAuth tokens are bound to one workspace, so omit it there.\n","name":"Conversions"}],"x-tagGroups":[{"name":"Links & Domains","tags":["Links","Domains","Workspaces"]},{"name":"Webhooks","tags":["Webhooks"]},{"name":"Reports","tags":["Clicks"]}]}