Links

Links

Create, list, update, and delete short links. QR codes use the same endpoints with `type: "QR"`.

POST /api/v1/links

Create a new short link or QR code.

Request Body

NameTypeRequiredDescription
urlstringRequiredThe destination URL to shorten
domainstringOptionalDomain selection (default: “auto”). Auto and explicit “u2l.ai” use u2l.ai only for trusted destinations; otherwise the API returns u.gy.
aliasstringOptionalCustom slug. Auto-generated if omitted
titlestringOptionalA user-friendly title for the link
tagsstring[]OptionalArray of tags for categorization Pro+
folderIdstringOptionalFolder ID to organize the link into Pro+
typestringOptional”SL” (short link) or “QR” (QR code). Default: “SL”
permanentbooleanOptional301 (true) or 302 (false) redirect. Default: true
passwordstringOptionalPassword-protect the link Advanced+
expiresAtnumberOptionalUnix timestamp (ms) when the link expires Advanced+
customOgobjectOptionalCustom social preview: { title, description, image } Advanced+
abTestobjectOptionalA/B testing: { enabled, destinationB, splitPercentage } Advanced+

With the default auto placement, destinations confirmed by the trusted-domain database use u2l.ai. Other allowed destinations use u.gy. Always read the returned domain or shortLink.

curl -X POST https://u2l.ai/api/v1/links \
  -H "Authorization: Bearer u2l_live_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/my-page",
    "alias": "my-link",
    "title": "My Marketing Link",
    "tags": ["marketing", "q1"]
  }'
const response = await fetch("https://u2l.ai/api/v1/links", {
  method: "POST",
  headers: {
    "Authorization": "Bearer u2l_live_your_api_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://example.com/my-page",
    alias: "my-link",
    title: "My Marketing Link",
    tags: ["marketing", "q1"],
  }),
});

const link = await response.json();
console.log(link.shortLink); // https://u2l.ai/my-link
import requests

response = requests.post(
    "https://u2l.ai/api/v1/links",
    headers={
        "Authorization": "Bearer u2l_live_your_api_key",
        "Content-Type": "application/json",
    },
    json={
        "url": "https://example.com/my-page",
        "alias": "my-link",
        "title": "My Marketing Link",
        "tags": ["marketing", "q1"],
    },
)

link = response.json()
print(link["shortLink"])  # https://u2l.ai/my-link
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "shortLink": "https://u2l.ai/my-link",
  "domain": "u2l.ai",
  "slug": "my-link",
  "destination": "https://example.com/my-page",
  "title": "My Marketing Link",
  "tags": ["marketing", "q1"],
  "hasPassword": false,
  "expiresAt": null,
  "permanent": true,
  "type": "SL",
  "createdAt": "2026-02-11T10:00:00.000Z",
  "updatedAt": "2026-02-11T10:00:00.000Z",
  "folderId": null,
  "clicks": 0
}

GET /api/v1/links

List all links with pagination, filtering, and sorting. Returns links across all domains by default.

Query Parameters

NameTypeRequiredDescription
pagenumberOptionalPage number (default: 1)
limitnumberOptionalItems per page, max 100 (default: 25)
typestringOptionalFilter by type: “SL” or “QR”
domainstringOptionalFilter by domain
folderIdstringOptionalFilter by folder ID
tagstringOptionalFilter by tag
searchstringOptionalSearch in slug, destination, and title
sortstringOptionalSort field: “createdAt”, “clicks”, or “title”
orderstringOptional”asc” or “desc” (default: “desc”)
curl "https://u2l.ai/api/v1/links?page=1&limit=25&sort=createdAt&order=desc" \
  -H "Authorization: Bearer u2l_live_your_api_key"
const params = new URLSearchParams({
  page: "1",
  limit: "25",
  sort: "createdAt",
  order: "desc",
});

const response = await fetch(`https://u2l.ai/api/v1/links?${params}`, {
  headers: {
    "Authorization": "Bearer u2l_live_your_api_key",
  },
});

const { links, pagination } = await response.json();
import requests

response = requests.get(
    "https://u2l.ai/api/v1/links",
    headers={"Authorization": "Bearer u2l_live_your_api_key"},
    params={"page": 1, "limit": 25, "sort": "createdAt", "order": "desc"},
)

data = response.json()
links = data["links"]
pagination = data["pagination"]
{
  "links": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "shortLink": "https://u2l.ai/my-link",
      "domain": "u2l.ai",
      "slug": "my-link",
      "destination": "https://example.com/my-page",
      "title": "My Marketing Link",
      "tags": ["marketing", "q1"],
      "hasPassword": false,
      "expiresAt": null,
      "permanent": true,
      "type": "SL",
      "createdAt": "2026-02-11T10:00:00.000Z",
      "updatedAt": "2026-02-11T10:00:00.000Z",
      "folderId": null,
      "clicks": 142
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 25,
    "total": 142,
    "totalPages": 6,
    "hasMore": true
  }
}

GET /api/v1/links/{domain}/{slug}

Retrieve a single link by its domain and slug.

Path Parameters

NameTypeRequiredDescription
domainstringRequiredThe link’s domain (e.g., “u2l.ai”)
slugstringRequiredThe link’s slug (e.g., “my-link”)
curl "https://u2l.ai/api/v1/links/u2l.ai/my-link" \
  -H "Authorization: Bearer u2l_live_your_api_key"
const response = await fetch("https://u2l.ai/api/v1/links/u2l.ai/my-link", {
  headers: {
    "Authorization": "Bearer u2l_live_your_api_key",
  },
});

const link = await response.json();
import requests

response = requests.get(
    "https://u2l.ai/api/v1/links/u2l.ai/my-link",
    headers={"Authorization": "Bearer u2l_live_your_api_key"},
)

link = response.json()
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "shortLink": "https://u2l.ai/my-link",
  "domain": "u2l.ai",
  "slug": "my-link",
  "destination": "https://example.com/my-page",
  "title": "My Marketing Link",
  "tags": ["marketing", "q1"],
  "hasPassword": false,
  "expiresAt": null,
  "permanent": true,
  "type": "SL",
  "createdAt": "2026-02-11T10:00:00.000Z",
  "updatedAt": "2026-02-11T10:00:00.000Z",
  "folderId": null,
  "clicks": 142
}

PATCH /api/v1/links/{domain}/{slug}

Update an existing link. Only send the fields you want to change.

Path Parameters

NameTypeRequiredDescription
domainstringRequiredThe link’s domain (e.g., “u2l.ai”)
slugstringRequiredThe link’s slug (e.g., “my-link”)

Request Body (all fields optional)

NameTypeRequiredDescription
destinationstringOptionalNew destination URL
titlestringOptionalUpdated title
tagsstring[]OptionalUpdated tags array Pro+
passwordstringOptionalSet or update password Advanced+
expiresAtnumberOptionalUpdated expiration timestamp Advanced+
permanentbooleanOptionalUpdate redirect type
customOgobjectOptionalUpdate social preview Advanced+
abTestobjectOptionalUpdate A/B testing config Advanced+
curl -X PATCH "https://u2l.ai/api/v1/links/u2l.ai/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/u2l.ai/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 updated = await response.json();
import requests

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

updated = response.json()
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "shortLink": "https://u2l.ai/my-link",
  "domain": "u2l.ai",
  "slug": "my-link",
  "destination": "https://example.com/new-page",
  "title": "Updated Title",
  "tags": ["marketing", "q1"],
  "hasPassword": false,
  "expiresAt": null,
  "permanent": true,
  "type": "SL",
  "createdAt": "2026-02-11T10:00:00.000Z",
  "updatedAt": "2026-02-11T12:30:00.000Z",
  "folderId": null,
  "clicks": 142
}

DELETE /api/v1/links/{domain}/{slug}

Permanently delete a link. This removes it from both the edge cache and the database.

Path Parameters

NameTypeRequiredDescription
domainstringRequiredThe link’s domain (e.g., “u2l.ai”)
slugstringRequiredThe link’s slug (e.g., “my-link”)
curl -X DELETE "https://u2l.ai/api/v1/links/u2l.ai/my-link" \
  -H "Authorization: Bearer u2l_live_your_api_key"
const response = await fetch("https://u2l.ai/api/v1/links/u2l.ai/my-link", {
  method: "DELETE",
  headers: {
    "Authorization": "Bearer u2l_live_your_api_key",
  },
});

const result = await response.json();
// { "message": "Link deleted successfully" }
import requests

response = requests.delete(
    "https://u2l.ai/api/v1/links/u2l.ai/my-link",
    headers={"Authorization": "Bearer u2l_live_your_api_key"},
)

result = response.json()
# {"message": "Link deleted successfully"}
{
  "message": "Link deleted successfully"
}