Links
Short links are the core object of the API. A link points a slug on one of your domains at a destination URL, and can carry UTM parameters, tags, an expiry date, and retargeting pixels.
| Method | Path | Scope |
|---|---|---|
GET | /v1/links | links:read |
POST | /v1/links | links:write |
GET | /v1/links/{id} | links:read |
PATCH | /v1/links/{id} | links:write |
DELETE | /v1/links/{id} | links:write |
The link object
{
"id": "9b1f4e2a-6c3d-4a17-9f2e-7c8d5a1b3e40",
"title": "Summer Sale",
"destination_url": "https://example.com/summer-sale?utm_source=newsletter",
"short_url": "go.acme.com/summer",
"slug": "summer",
"hostname": "go.acme.com",
"utm_params": { "utm_source": "newsletter" },
"tags": ["q3", "email"],
"expires_at": "2026-12-31T00:00:00.000000Z",
"pixel_ids": ["3f9c8a71-2b4d-4e60-8a15-9d7c6b3e21f8"],
"clicks": 128,
"status": true,
"created_at": "2026-08-28T10:14:02.000000Z",
"updated_at": "2026-08-28T11:02:44.000000Z"
}| Field | Type | Description |
|---|---|---|
id | uuid | The link’s identifier |
title | string | null | Title scraped from the destination page’s Open Graph metadata |
destination_url | string | Where the link redirects to, including any UTM parameters that were applied |
short_url | string | The full short link, hostname and slug combined |
slug | string | The path portion of the short link |
hostname | string | null | The custom domain in use; null when the link is on the shared Link Squeeze domain |
utm_params | object | The UTM parameters applied to the destination URL; [] when none are set |
tags | array of strings | Your own labels for the link |
expires_at | timestamp | null | When the link stops resolving; null means it never expires |
pixel_ids | array of uuids | Retargeting pixels that fire when the link is clicked |
clicks | integer | Total clicks recorded for the link |
status | boolean | Whether the link is currently active |
created_at | timestamp | When the link was created |
updated_at | timestamp | When the link was last modified |
utm_params is returned as an empty array ([]) rather than an empty object
when a link has no UTM parameters. This is a quirk of JSON encoding an empty
PHP array — treat an empty array and an empty object as equivalent here.
List links
GET /v1/linksScope: links:read
Returns your links, newest first, in the standard paginated shape.
| Query parameter | Type | Description |
|---|---|---|
page | integer | Page to return. Defaults to 1. |
per_page | integer | Results per page. Defaults to 15, maximum 100. |
curl "https://app.linksqueeze.io/api/v1/links?per_page=50" \
-H "Authorization: Bearer $LINKSQUEEZE_API_KEY" \
-H "Accept: application/json"Create a link
POST /v1/linksScope: links:write
| Field | Type | Required | Description |
|---|---|---|---|
destination_url | string | Yes | The URL to redirect to. Must be a valid URL, maximum 2048 characters. |
slug | string | No | The short link path. Letters, numbers, dashes, and underscores only, maximum 255 characters. Must be globally unique. Generated for you if omitted. |
hostname | string | No | A custom domain registered to your account. Defaults to the shared Link Squeeze domain. |
utm_params | object | No | Any of utm_source, utm_medium, utm_campaign, utm_term, utm_content. Each maximum 255 characters. |
tags | array of strings | No | Your own labels. Each maximum 255 characters. |
expires_at | timestamp | No | When the link should stop resolving. Must be in the future. |
pixel_ids | array of uuids | No | Retargeting pixels to attach. Each must be a pixel registered to your account. |
Returns 201 Created with the link object.
curl -X POST https://app.linksqueeze.io/api/v1/links \
-H "Authorization: Bearer $LINKSQUEEZE_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"destination_url": "https://example.com/summer-sale",
"slug": "summer",
"hostname": "go.acme.com",
"utm_params": {
"utm_source": "newsletter",
"utm_medium": "email",
"utm_campaign": "summer-2026"
},
"tags": ["q3", "email"],
"expires_at": "2026-12-31T00:00:00Z",
"pixel_ids": ["3f9c8a71-2b4d-4e60-8a15-9d7c6b3e21f8"]
}'How domains are referenced
Links reference a domain by its hostname, not by its domain UUID, so you can create a link on go.acme.com without first looking up the domain’s id.
The hostname must be a domain registered to your account. One that is not — including a domain owned by another account — is rejected with 422:
{
"error": {
"code": "validation_error",
"message": "The given data was invalid.",
"errors": {
"hostname": ["This hostname is not registered to your account."]
}
}
}Omit hostname (or send null) to put the link on the shared Link Squeeze short domain. In that case hostname comes back as null in the response, and short_url shows the shared domain.
How UTM parameters are applied
UTM parameters are baked into the destination URL at write time. Creating a link with destination_url of https://example.com/product and utm_source of newsletter returns:
{
"destination_url": "https://example.com/product/?utm_source=newsletter",
"utm_params": { "utm_source": "newsletter" }
}The utm_params object is also stored separately so you can read back what was applied, but there is no separate “clean” URL — destination_url is always the final URL a visitor lands on. This has consequences when updating a link, described below.
Retrieve a link
GET /v1/links/{id}Scope: links:read
curl https://app.linksqueeze.io/api/v1/links/9b1f4e2a-6c3d-4a17-9f2e-7c8d5a1b3e40 \
-H "Authorization: Bearer $LINKSQUEEZE_API_KEY" \
-H "Accept: application/json"A link belonging to another account returns 404 not_found, the same as a link that does not exist — the API does not disclose that an id exists on someone else’s account.
Update a link
PATCH /v1/links/{id}Scope: links:write
Every field is optional. Fields you do not send are left untouched.
| Field | Type | Description |
|---|---|---|
destination_url | string | New destination URL. Required when sending utm_params. |
slug | string | New slug. Must be globally unique. |
hostname | string | null | Move the link to another of your domains, or send null to move it back to the shared domain. |
utm_params | object | null | Replaces the existing UTM parameters. Must be sent together with destination_url. |
tags | array of strings | null | Replaces the existing tags. |
expires_at | timestamp | null | New expiry, or null to remove it. Must be in the future. |
pixel_ids | array of uuids | null | Replaces the attached pixels. Send [] to detach all of them. |
curl -X PATCH https://app.linksqueeze.io/api/v1/links/9b1f4e2a-6c3d-4a17-9f2e-7c8d5a1b3e40 \
-H "Authorization: Bearer $LINKSQUEEZE_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{ "tags": ["rebrand"] }'Returns 200 OK with the updated link object.
utm_params cannot be updated on its own. Because UTM parameters are
baked into the stored destination URL and no separate clean URL is kept,
re-applying them to an already-tagged URL would risk duplicating query
parameters. Send destination_url alongside utm_params — a utm_params-only
patch is rejected with 422.
Array fields are replaced, not merged
tags, pixel_ids, and utm_params are replaced wholesale by the value you send. To add one tag to a link that already has two, send all three.
Fields you omit entirely are preserved. Changing destination_url without mentioning pixel_ids, for example, keeps the link’s existing pixels attached.
Clearing a hostname
Send "hostname": null to move a link off a custom domain and back onto the shared Link Squeeze domain. The response returns hostname as null and short_url rewritten to the shared domain.
Delete a link
DELETE /v1/links/{id}Scope: links:write
Returns 204 No Content with an empty body.
curl -X DELETE https://app.linksqueeze.io/api/v1/links/9b1f4e2a-6c3d-4a17-9f2e-7c8d5a1b3e40 \
-H "Authorization: Bearer $LINKSQUEEZE_API_KEY" \
-H "Accept: application/json"Deleting a link stops it resolving immediately. Anyone who has already shared or printed the short link will get your domain’s not-found page from that point on.
Events
Creating a link through the API fires the link.created webhook event, exactly once, with the complete link record. See Webhooks.