Links

Update a link

Updates a link. Only the fields you send are changed. Send password: null to remove a password; send expiresAt: null to remove expiration. Destination changes on u2l.ai links re-run the trust check - untrusted destinations are rejected (move the link to another domain instead).

PATCH https://u2l.ai/api/v1/links/{domain}/{slug}

Authorizations

Authorizationstringrequired

Bearer authentication header of the form Bearer <token>, where <token> is your U2L API key (u2l_live_...). Create one in the dashboard under Settings > API.

Path Parameters

domainstringrequired

The link's domain (e.g. u.gy or u2l.ai).

slugstringrequired

The link's slug (the part after the domain).

Body

destinationstring

New destination URL.

titlestring
tagsstring[]
passwordstring

New password; send null to remove (Advanced plan or above).

expiresAtstring

New expiration; send null to remove.

permanentboolean
customOgobject

Custom social preview (Advanced plan or above).

customOg.titlestring
customOg.descriptionstring
customOg.imagestring

Image URL.

abTestobject

A/B testing config (Advanced plan or above).

abTest.enabledboolean
abTest.destinationBstring

Variant B destination URL.

abTest.splitPercentageinteger

Traffic percentage to destination A. Defaults to 50.

Response 200

idstring

Link ID (UUID).

slugstring

The part after the domain.

domainstring

The link's domain.

destinationstring

Where the link redirects to.

titlestring

Optional title.

tagsstring[]
hasPasswordboolean
expiresAtstring

Expiration time, if set.

permanentboolean

true = 301 redirect, false = 302.

typestring

SL = short link, QR = QR code, PG = link-in-bio page. One of: SL, QR, PG.

createdAtstring
updatedAtstring
folderIdstring
clicksinteger

Total clicks.

ogTitlestring

Custom social preview title.

ogDescriptionstring
ogImagestring
abTestEnabledboolean
destinationBstring

A/B variant destination.

splitPercentageinteger

Traffic percentage to destination A.

qrStyleobject

QR styling options (QR links only).

externalBrowserboolean

Open in the phone's default browser when tapped inside in-app browsers (Android).

Errors

400 The destination was rejected by safety or trust checks.
401 Missing or invalid API key.
403 Your plan does not include this feature, or a limit was reached.
404 The resource does not exist or is not yours.
429 Rate limit exceeded. Check X-RateLimit-Reset for when the window resets.

See Rate Limits & Errors for the error envelope and per-plan limits.

curl -X PATCH https://u2l.ai/api/v1/links/u.gy/my-link \
  -H "Authorization: Bearer u2l_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
  "destination": "https://example.com/new-page",
  "title": "Updated title"
}'
const response = await fetch("https://u2l.ai/api/v1/links/u.gy/my-link", {
  method: "PATCH",
  headers: {
    "Authorization": "Bearer u2l_live_your_api_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "destination": "https://example.com/new-page",
    "title": "Updated title"
  }),
});

const data = await response.json();
console.log(data);
import requests

response = requests.patch(
    "https://u2l.ai/api/v1/links/u.gy/my-link",
    headers={"Authorization": "Bearer u2l_live_your_api_key"},
    json={
      "destination": "https://example.com/new-page",
      "title": "Updated title"
    },
)

print(response.json())
package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{
  "destination": "https://example.com/new-page",
  "title": "Updated title"
}`)
	req, _ := http.NewRequest("PATCH", "https://u2l.ai/api/v1/links/u.gy/my-link", body)
	req.Header.Set("Authorization", "Bearer u2l_live_your_api_key")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()

	data, _ := io.ReadAll(res.Body)
	fmt.Println(string(data))
}
{
  "id": "9f0c2f9e-3b7a-4c1d-8e5f-2a6b7c8d9e0f",
  "slug": "my-link",
  "domain": "u.gy",
  "destination": "https://example.com/new-page",
  "title": "Updated title",
  "tags": [
    "campaign"
  ],
  "hasPassword": false,
  "expiresAt": null,
  "permanent": true,
  "type": "SL",
  "createdAt": "2026-07-20T10:30:00.000Z",
  "updatedAt": "2026-07-21T08:12:00.000Z",
  "folderId": null,
  "clicks": 128
}