API documentation
Create, update and analyse short links from your own code. The API is JSON over HTTPS and is available on every plan, including Free.
- Base URL
- https://urelf.com/api/v1
- OpenAPI 3.1 spec
- /api/v1/openapi.json
Authentication
Create an API key in Settings → API keys and send it in the Authorization header of every request. Keys start with urelf_ and are shown only once, so store them somewhere safe. Free accounts can have up to 2 keys. Your email address must be verified.
Authorization: Bearer urelf_your_api_keyKeep keys on your server. Never put them in browser code or mobile apps. If a key leaks, delete it in Settings and create a new one.
Rate limits & quotas
Requests are rate-limited per account, per minute. Creating links also counts against your plan’s daily quota (resets at midnight UTC) and total quota (deleting a link frees a slot).
| Plan | Requests / minute | New links / day | Total links |
|---|---|---|---|
| Free | 60 | 10 | 100 |
| Pro(coming soon) | 600 | 500 | 10,000 |
| Business(coming soon) | 3,000 | 2,000 | 100,000 |
Response headers
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset(seconds until the window resets): on every successful response.X-Quota-Daily-Remaining,X-Quota-Total-Remaining: onPOST /api/v1/links. UseGET /api/v1/meto read your quota at any time.Retry-After(seconds): on429responses.
Errors
Errors use standard HTTP status codes and a consistent JSON body. code is stable and safe to branch on; message is human-readable and safe to show to users.
{
"error": {
"code": "DAILY_QUOTA_EXCEEDED",
"message": "You can create 10 links per day on the Free plan. The limit resets at midnight UTC.",
"details": {
"resetsAt": "2026-10-14T00:00:00.000Z"
}
}
}| Code | Status | Meaning |
|---|---|---|
BAD_REQUEST | 400 | The request body or query is invalid. details lists each problem. |
INVALID_URL | 400 | The destination isn’t a valid public http(s) URL. |
UNSAFE_URL | 400 | The destination is blocked (malware, phishing, private network, another shortener or URelf itself). |
INVALID_SLUG | 400 | The custom short name doesn’t follow the naming rules. |
RESERVED_SLUG | 400 | The short name is reserved for URelf pages. |
UNAUTHORIZED | 401 | Missing, invalid or revoked API key. |
EMAIL_NOT_VERIFIED | 403 | Verify your email address before using the API. |
FORBIDDEN | 403 | You’re not allowed to do this. |
ACCOUNT_SUSPENDED | 403 | The account has been suspended. |
TOTAL_QUOTA_EXCEEDED | 403 | You’ve reached your plan’s total link limit. Delete a link to free a slot. |
NOT_FOUND | 404 | The link doesn’t exist or isn’t yours. |
SLUG_TAKEN | 409 | The custom short name is already in use. |
DAILY_QUOTA_EXCEEDED | 429 | You’ve created today’s maximum number of links. details.resetsAt says when it resets (midnight UTC). |
RATE_LIMITED | 429 | Too many requests. Wait for the number of seconds in Retry-After. |
INTERNAL | 500 | Something went wrong on our side. Retry with backoff. |
SERVICE_UNAVAILABLE | 503 | A dependency is temporarily unavailable. Retry with backoff. |
Endpoints
Create a link
POST/api/v1/links
Counts against your daily and total quotas. The response includes X-Quota-Daily-Remaining and X-Quota-Total-Remaining. The destination is checked for malware and phishing before the link is created.
JSON body
urlstring, required | Destination, up to 2,048 characters. http(s) only; https:// is assumed if omitted. |
slugstring | Custom short name: 3–32 lower-case letters, digits or single hyphens. Omit to generate one. |
titlestring | Label for your own reference, up to 200 characters. |
expiresAtISO 8601 date-time | Optional expiry in the future. Links never expire by default. |
curl -X POST https://urelf.com/api/v1/links \
-H "Authorization: Bearer urelf_your_api_key" \
-H "Content-Type: application/json" \
-d '{"url": "https://shop.example.com/collections/spring?utm_source=newsletter", "slug": "spring-sale", "title": "Spring sale newsletter"}'{
"id": "cm9x2k7d40001qz8l3f6h2abc",
"slug": "spring-sale",
"shortUrl": "https://urelf.com/spring-sale",
"url": "https://shop.example.com/collections/spring?utm_source=newsletter",
"title": "Spring sale newsletter",
"status": "active",
"expiresAt": null,
"clickCount": 0,
"lastClickedAt": null,
"createdAt": "2026-10-01T09:15:00.000Z",
"updatedAt": "2026-10-01T09:15:00.000Z"
}List links
GET/api/v1/links
Your links, newest first. Pass nextCursor from the response as cursor to get the next page; it is null on the last page.
Query parameters
limitinteger | 1–100, default 25. |
cursorstring | From a previous response’s nextCursor. |
qstring | Search short names, destinations and titles. |
curl "https://urelf.com/api/v1/links?limit=10" \
-H "Authorization: Bearer urelf_your_api_key"{
"items": [
{
"id": "cm9x2k7d40001qz8l3f6h2abc",
"slug": "spring-sale",
"shortUrl": "https://urelf.com/spring-sale",
"url": "https://shop.example.com/collections/spring?utm_source=newsletter",
"title": "Spring sale newsletter",
"status": "active",
"expiresAt": null,
"clickCount": 1284,
"lastClickedAt": "2026-10-12T18:24:03.000Z",
"createdAt": "2026-10-01T09:15:00.000Z",
"updatedAt": "2026-10-01T09:15:00.000Z"
}
],
"nextCursor": null
}Get a link
GET/api/v1/links/{id}
Returns a single link by its ID.
curl https://urelf.com/api/v1/links/cm9x2k7d40001qz8l3f6h2abc \
-H "Authorization: Bearer urelf_your_api_key"{
"id": "cm9x2k7d40001qz8l3f6h2abc",
"slug": "spring-sale",
"shortUrl": "https://urelf.com/spring-sale",
"url": "https://shop.example.com/collections/spring?utm_source=newsletter",
"title": "Spring sale newsletter",
"status": "active",
"expiresAt": null,
"clickCount": 1284,
"lastClickedAt": "2026-10-12T18:24:03.000Z",
"createdAt": "2026-10-01T09:15:00.000Z",
"updatedAt": "2026-10-01T09:15:00.000Z"
}Update a link
PATCH/api/v1/links/{id}
Send only the fields you want to change: url, slug, title or expiresAt. Set title or expiresAt to null to clear them. Changes take effect immediately.
curl -X PATCH https://urelf.com/api/v1/links/cm9x2k7d40001qz8l3f6h2abc \
-H "Authorization: Bearer urelf_your_api_key" \
-H "Content-Type: application/json" \
-d '{"url": "https://shop.example.com/collections/autumn"}'{
"id": "cm9x2k7d40001qz8l3f6h2abc",
"slug": "spring-sale",
"shortUrl": "https://urelf.com/spring-sale",
"url": "https://shop.example.com/collections/autumn",
"title": "Spring sale newsletter",
"status": "active",
"expiresAt": null,
"clickCount": 1284,
"lastClickedAt": "2026-10-12T18:24:03.000Z",
"createdAt": "2026-10-01T09:15:00.000Z",
"updatedAt": "2026-10-13T10:02:11.000Z"
}Delete a link
DELETE/api/v1/links/{id}
The short link stops working immediately. Deleting frees a slot in your total quota, but not in today’s count.
curl -X DELETE https://urelf.com/api/v1/links/cm9x2k7d40001qz8l3f6h2abc \
-H "Authorization: Bearer urelf_your_api_key"(empty body)Get click statistics
GET/api/v1/links/{id}/stats
Daily clicks and unique visitors for the last days days (1–730, default 30), plus top referrers, countries (ISO codes), devices and browsers. Breakdowns cover your plan’s detailed-data window; totalClicks is all-time. Bots are excluded.
Query parameters
daysinteger | 1–730, default 30. |
curl "https://urelf.com/api/v1/links/cm9x2k7d40001qz8l3f6h2abc/stats?days=3" \
-H "Authorization: Bearer urelf_your_api_key"{
"days": 3,
"totalClicks": 1284,
"series": [
{
"day": "2026-10-11",
"clicks": 96,
"uniques": 81
},
{
"day": "2026-10-12",
"clicks": 143,
"uniques": 120
},
{
"day": "2026-10-13",
"clicks": 37,
"uniques": 33
}
],
"topReferrers": [
{
"name": "mail.google.com",
"clicks": 121
},
{
"name": "twitter.com",
"clicks": 64
}
],
"topCountries": [
{
"name": "DE",
"clicks": 102
},
{
"name": "HU",
"clicks": 77
}
],
"devices": [
{
"name": "mobile",
"clicks": 170
},
{
"name": "desktop",
"clicks": 106
}
],
"browsers": [
{
"name": "Chrome",
"clicks": 150
},
{
"name": "Safari",
"clicks": 98
}
]
}Check a short name
GET/api/v1/slugs/{slug}
Whether a custom short name is free to use. When it isn’t, reason explains why: it’s invalid, reserved or already taken.
curl https://urelf.com/api/v1/slugs/spring-sale \
-H "Authorization: Bearer urelf_your_api_key"{
"available": false,
"reason": "Already taken."
}Get your account and usage
GET/api/v1/me
Your plan and how much of your daily and total quota you’ve used.
curl https://urelf.com/api/v1/me \
-H "Authorization: Bearer urelf_your_api_key"{
"id": "cm9x1a2b30000qz8l7k1d9xyz",
"name": "Ada Lovelace",
"email": "[email protected]",
"plan": "FREE",
"usage": {
"plan": "FREE",
"today": {
"used": 3,
"limit": 10,
"resetsAt": "2026-10-14T00:00:00.000Z"
},
"total": {
"used": 42,
"limit": 100
}
}
}