v1.3
OpenAPI 3.0.0

Linkly URL Shortener API

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.

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.

Looking for step-by-step guides, tutorials, and FAQs? The Linkly API documentation covers a broader range of topics. This page is the complete endpoint reference.

Authentication

All API requests require an API key. You can find your API key in your Linkly workspace settings.

The recommended way is to pass it as a Bearer token in the Authorization header:

Authorization: Bearer YOUR_API_KEY

You can also use HTTP Basic Auth, with your API key as the username and an empty password:

Authorization: Basic base64(YOUR_API_KEY:)

Or, 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:

GET https://api.linklyhq.com/api/v1/workspaces?api_key=YOUR_API_KEY

A 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.

Base URL

https://api.linklyhq.com/api/v1

Workspaces

Most endpoints are scoped to a workspace. Use GET /workspaces to list your available workspaces and retrieve their IDs.

Rate Limits

API requests are rate-limited per API key. When you exceed the limit, the API returns 429 Too Many Requests. Check the response body for your current usage and limit.

Errors

Errors 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:

{ "error": "Not authorized", "code": "unauthorized" }
Status code Meaning
400 bad_request Missing or malformed parameters.
401 unauthorized Missing or invalid API key.
403 forbidden Your plan or permissions don't allow this action.
404 not_found The resource doesn't exist, or your key can't access it.
429 rate_limit_exceeded You've exceeded a rate or usage limit.
500 internal_error Something went wrong on our side.

Validation failures return 400 and may include field-level details (e.g. { "slug": ["is invalid"] }) in place of the envelope above.

Server:https://api.linklyhq.com
Client Libraries

Webhooks (Collapsed)

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.

A 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.

Delivery is fire-and-forget with a 5-second timeout and no retries, so your endpoint should respond quickly with a 2xx status.

Event types

Every subscription receives all event types for its scope. Branch on the top-level event field:

event Sent when
click A short link is clicked. The body includes a click object with the request metadata.
link.created A new link is created.
link.updated A link is changed. Fires on every update, including partial/autosaved edits, so expect several per editing session.
link.deleted A link is deleted. The link object keeps the slug/domain it had before deletion.

Click payload

Each request body is a JSON object shaped like this:

{
  "event": "click",
  "timestamp": "2026-06-09T12:34:56.000000Z",
  "link": {
    "id": 30,
    "url": "https://www.example.com",
    "full_url": "https://go.yourcompany.com/promo",
    "slug": "/promo",
    "workspace_id": 42,
    "destination": "https://www.example.com?utm_source=newsletter",
    "rules": []
  },
  "click": {
    "browser_name": "Chrome",
    "platform": "Mac",
    "destination": "https://www.example.com?utm_source=newsletter",
    "country": "US",
    "referer": "https://twitter.com/",
    "user_agent": "Mozilla/5.0 ...",
    "accept_language": "en-US",
    "bot_name": null,
    "params": {}
  }
}

The 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.

Link lifecycle payload

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:

{
  "event": "link.created",
  "timestamp": "2026-06-20T12:34:56.000000Z",
  "link": {
    "id": 30,
    "url": "https://www.example.com",
    "full_url": "https://go.yourcompany.com/promo",
    "slug": "/promo",
    "domain": "go.yourcompany.com",
    "workspace_id": 42,
    "name": "Summer promo",
    "enabled": true,
    "inserted_at": "2026-06-20T12:34:56Z",
    "updated_at": "2026-06-20T12:34:56Z",
    "rules": []
  }
}

List webhooks for a workspace

Get all webhook subscriptions for a specific workspace.

Path Parameters
  • workspace_id
    Type: integer
    required

    The ID of the workspace

Responses
  • application/json
  • application/json
Callbacks
Request Example for get/api/v1/workspace/{workspace_id}/webhooks
curl 'https://api.linklyhq.com/api/v1/workspace/42/webhooks?api_key=YOUR_SECRET_TOKEN'
[
  {
    "id": "https://hooks.zapier.com/hooks/catch/123456/abcdef/"
  }
]

Subscribe webhook to a workspace

Subscribe a webhook URL to receive events for every link in the workspace. The endpoint receives a POST for each click, link.created, link.updated, and link.deleted. Branch on the JSON event field; see the Webhooks section for payload shapes.

Path Parameters
  • workspace_id
    Type: integer
    required

    The ID of the workspace to subscribe to

Body·WebhookSubscribeRequest
required

Webhook subscription

Request body for subscribing a webhook

  • url
    Type: stringFormat: uri
    required

    The webhook URL to receive click notifications

Responses
  • application/json
  • application/json
  • application/json
Callbacks
Request Example for post/api/v1/workspace/{workspace_id}/webhooks
curl 'https://api.linklyhq.com/api/v1/workspace/42/webhooks?api_key=YOUR_SECRET_TOKEN' \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "url": "https://hooks.zapier.com/hooks/catch/123456/abcdef/"
}'
{
  "id": "https://hooks.zapier.com/hooks/catch/123456/abcdef/"
}

Unsubscribe webhook from a workspace

Remove a webhook subscription from a workspace. The hook_id is the URL-encoded webhook URL.

Path Parameters
  • workspace_id
    Type: integer
    required

    The ID of the workspace

  • hook_id
    Type: string
    required

    The webhook URL (URL-encoded)

Responses
  • application/json
  • application/json
Callbacks
Request Example for delete/api/v1/workspace/{workspace_id}/webhooks/{hook_id}
curl 'https://api.linklyhq.com/api/v1/workspace/42/webhooks/https%3A%2F%2Fhooks.example.com%2Fabc123?api_key=YOUR_SECRET_TOKEN' \
  --request DELETE
string

Clicks (Collapsed)

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.

Get click analytics

Retrieve click analytics for a workspace. Filter by link, date range, country, and more. Returns time-series data suitable for charting.

Path Parameters
  • workspace_id
    Type: string
    required

    The id of the Workspace

Query Parameters
  • Type: string

    The id of a single Link

  • Type: string

    Filter clicks by multiple links. Provide a hyphen-separated list of link IDs.

  • start
    Type: string

    The start date for the date range (format: YYYY-MM-DD or YYYY-MM-DDTHH:MM:SSZ)

  • end
    Type: string

    The end date for the date range (format: YYYY-MM-DD or YYYY-MM-DDTHH:MM:SSZ)

  • country
    Type: string

    Filter clicks by country using ISO 3166-1 alpha-2 country code e.g US

  • browser
    Type: string

    Filter clicks by browser name e.g Chrome, Firefox, Safari

  • platform
    Type: string

    Filter clicks by platform/operating system e.g Windows, Mac, iOS, Android

  • referer
    Type: string

    Filter clicks by referrer domain

  • isp
    Type: string

    Filter clicks by Internet Service Provider name

  • bots
    Type: boolean

    Set to false to exclude bot clicks from the results

  • unique
    Type: boolean

    Set to true to only include unique clicks in the results

  • format
    Type: stringenum

    Specify the format of the response. Available options are 'json' (default), 'csv', or 'tsv'.

    values
    • json
    • csv
    • tsv
  • pivot
    enum
    const:  
    link_id

    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.

    values
    • link_id
  • timezone
    Type: string

    The timezone to use for date/time calculations

  • frequency
    Type: stringenum

    The frequency of data points in the response. Available options are 'day' (default) or 'hour'.

    values
    • day
    • hour
Responses
  • application/json
  • application/json
  • application/json
Callbacks
Request Example for get/api/v1/workspace/{workspace_id}/clicks
curl 'https://api.linklyhq.com/api/v1/workspace/42/clicks?link_id=24&link_ids=24-25-26&start=&end=&country=&browser=&platform=&referer=&isp=&bots=false&unique=false&format=json&pivot=link_id&timezone=America%2FNew_York&frequency=day&api_key=YOUR_SECRET_TOKEN'
{
  "traffic": [
    {
      "t": "2026-06-01",
      "y": 12
    },
    {
      "t": "2026-06-02",
      "y": 8
    },
    {
      "t": "2026-06-03",
      "y": 21
    }
  ]
}

Get click counts grouped by dimension

Retrieve click analytics grouped by a specific dimension (counter). Returns aggregated counts for each unique value of the selected dimension.

Path Parameters
  • workspace_id
    Type: string
    required

    The id of the Workspace

  • counter
    Type: stringenum
    required

    The dimension to group clicks by. Options: country, platform, browser, referer, isp, link_id, top_params

    values
    • country
    • platform
    • browser
    • referer
    • isp
    • link_id
    • top_params
Query Parameters
  • Type: string

    The id of a single Link

  • Type: string

    Hyphen-separated list of Link IDs

  • start
    Type: string

    The start date for the date range (format: YYYY-MM-DD)

  • end
    Type: string

    The end date for the date range (format: YYYY-MM-DD)

  • country
    Type: string

    Filter by country using ISO 3166-1 alpha-2 country code

  • bots
    Type: boolean

    Set to false to exclude bot clicks from the results

  • unique
    Type: boolean

    Set to true to only count unique clicks

  • format
    Type: stringenum

    Specify the format of the response. Available options are 'json' (default), 'csv', or 'tsv'.

    values
    • json
    • csv
    • tsv
Responses
  • application/json
  • application/json
  • application/json
  • application/json
Callbacks
Request Example for get/api/v1/workspace/{workspace_id}/clicks/counters/{counter}
curl 'https://api.linklyhq.com/api/v1/workspace/42/clicks/counters/country?link_id=24&link_ids=24-25-26&start=&end=&country=&bots=false&unique=false&format=json&api_key=YOUR_SECRET_TOKEN'
{
  "total": 215,
  "values": [
    {
      "count": 120,
      "value": "US"
    },
    {
      "count": 64,
      "value": "GB"
    },
    {
      "count": 31,
      "value": "DE"
    }
  ]
}

Models