API docs

The urlxo API is JSON over HTTPS. Base URL:

https://urlxo.link/api/v1

Authentication

Create a key under Account and API and send it as a Bearer token. Keys act as your account, so keep them on the server.

curl https://urlxo.link/api/v1/me \
  -H "Authorization: Bearer $URLXO_KEY" \
  -H "Accept: application/json"

Create a link

POST /links

FieldTypeNotes
urlstringRequired. http or https, up to 2048 characters. A missing scheme becomes https.
codestringOptional alias, 3 to 32 of A-Z a-z 0-9 _ -. Case sensitive. Generated when empty.
titlestringOptional label for your dashboard.
passwordstringOptional. Visitors must enter it before the redirect.
expires_atISO 8601Optional. Must be in the future. After it, the link returns 410.
max_clicksintegerOptional cap on counted clicks.
is_activebooleanDefaults to true.
curl -X POST https://urlxo.link/api/v1/links \
  -H "Authorization: Bearer $URLXO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/launch","code":"launch","expires_at":"2027-01-31T23:59:00Z"}'

Returns 201 with the link object.

List links

GET /links?q=launch&per_page=25&page=1

q searches alias, destination and title. per_page goes up to 100. The response has data and meta with current_page, per_page, total and last_page.

Get a link

GET /links/{code}

Update a link

PATCH /links/{code} with any of the create fields. Send "password": null to remove a password and "expires_at": null to remove the expiry. Changing code moves the link and the old short URL stops working.

curl -X PATCH https://urlxo.link/api/v1/links/launch \
  -H "Authorization: Bearer $URLXO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/launch-v2"}'

Delete a link

DELETE /links/{code} returns 204. Its click history is deleted too.

Click stats

GET /links/{code}/stats?days=30, where days is 1 to 365 and includes today (UTC).

{
  "data": {
    "code": "launch",
    "all_time_clicks": 1284,
    "from": "2026-09-20",
    "to": "2026-10-19",
    "total": 912,
    "unique": 733,
    "daily": [{ "date": "2026-09-20", "clicks": 18 }],
    "countries": [{ "key": "NL", "clicks": 301 }],
    "referrers": [{ "key": "Direct", "clicks": 410 }],
    "devices": [{ "key": "mobile", "clicks": 577 }],
    "browsers": [{ "key": "Chrome", "clicks": 488 }],
    "os": [{ "key": "iOS", "clicks": 341 }]
  }
}

Countries are ISO 3166-1 alpha-2 codes. Bots, crawlers and chat link previews are not counted.

Link object

{
  "id": 42,
  "code": "launch",
  "short_url": "https://urlxo.link/launch",
  "url": "https://example.com/launch",
  "title": null,
  "has_password": false,
  "expires_at": "2027-01-31T23:59:00+00:00",
  "max_clicks": null,
  "clicks": 0,
  "is_active": true,
  "last_clicked_at": null,
  "created_at": "2026-10-19T09:12:44+00:00",
  "updated_at": "2026-10-19T09:12:44+00:00"
}

Errors and limits

StatusMeaning
401Missing or revoked key.
404No link with that code in your account.
422Validation failed. errors maps each field to its messages.
429Over 120 requests per minute for this key's account.
{
  "message": "This alias is already taken.",
  "errors": { "code": ["This alias is already taken."] }
}