API documentation
A small REST API over JSON. Every endpoint lives under https://tinylink.r3x.site/api/v1,
takes and returns JSON, and authenticates with a bearer token.
Authentication
Create a key under API keys, then send it on every request. Keys are stored only as SHA-256 digests, so a lost key must be revoked and replaced.
Authorization: Bearer tl_live_xxxxxxxxxxxxxxxxxxxx
X-API-Key: <key> works too, if that is easier for your client.
Conventions
- Successful responses wrap the payload in
{"data": …}; lists add{"meta": …}. - Errors return the matching HTTP status and
{"error": "message"}. - Rate limit: 120 requests per minute per key. Exceeding it returns
429with aRetry-Afterheader. - Timestamps are UTC, formatted
YYYY-MM-DD HH:MM:SS.
Endpoints
Create a short link. Only url is required.
curl -X POST https://tinylink.r3x.site/api/v1/links \
-H "Authorization: Bearer $TINYLINK_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/a/very/long/path",
"slug": "launch",
"title": "Spring launch",
"password": "hunter2",
"expires_at": "2026-12-31 23:59:00",
"max_clicks": 500,
"fetch_og": true,
"utm": { "utm_source": "twitter", "utm_medium": "social" }
}'
{
"data": {
"slug": "launch",
"short_url": "https://r3x.site/launch",
"target_url": "https://example.com/a/very/long/path",
"qr": "https://tinylink.r3x.site/qr/launch.svg",
"clicks": 0,
"is_active": true,
"protected": true,
"expires_at": "2026-12-31 23:59:00",
"max_clicks": 500,
"utm": { "utm_source": "twitter", "utm_medium": "social" },
"card": { "title": "Example", "description": "…", "image": "https://…" },
"created_at": "2026-08-30 10:14:02"
}
}
List your links. Query parameters: page (default 1), limit (max 100),
search.
curl "https://tinylink.r3x.site/api/v1/links?limit=10&search=launch" \
-H "Authorization: Bearer $TINYLINK_KEY"
Fetch a single link.
Update any subset of url, slug, title, password,
expires_at, max_clicks, is_active, utm,
and the og_* card fields. Send "password": "" to remove a password.
curl -X PATCH https://tinylink.r3x.site/api/v1/links/launch \
-H "Authorization: Bearer $TINYLINK_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/new","is_active":false}'
Delete a link and its click history. The slug becomes available again.
Analytics for one link. ?days=N controls the timeline window (1–365, default 30).
{
"data": {
"slug": "launch",
"summary": { "total": 214, "humans": 198, "unique": 171, "bots": 16, "last": "…" },
"timeline": [ { "day": "2026-08-01", "hits": 12 }, … ],
"referrers": [ { "label": "twitter.com", "hits": 88 }, … ],
"browsers": [ … ], "devices": [ … ], "countries": [ … ]
}
}
Manage bio pages. Send blocks as an ordered array to replace the page contents in one call.
curl -X POST https://tinylink.r3x.site/api/v1/pages \
-H "Authorization: Bearer $TINYLINK_KEY" \
-H "Content-Type: application/json" \
-d '{
"slug": "me",
"title": "R3X",
"bio": "Building things on the internet.",
"theme": "midnight",
"accent": "#6366f1",
"blocks": [
{ "kind": "header", "label": "Projects" },
{ "kind": "link", "label": "Portfolio", "url": "https://r3x.site", "icon": "🌐" },
{ "kind": "social", "label": "GitHub", "url": "https://github.com/…", "icon": "🐙" }
]
}'
The authenticated account plus headline stats. Useful for verifying a key.
Unauthenticated liveness check.
QR codes
Every link and bio page has a QR image, generated on the fly with no external service.
scale accepts 2–20.
https://tinylink.r3x.site/qr/launch.svg?scale=8 # vector, ideal for print
https://tinylink.r3x.site/qr/launch.png?scale=12 # raster, ideal for slides
https://tinylink.r3x.site/qr?data=https://example.com # ad-hoc, any URL
Errors
| 400 | Bad request — invalid URL, taken slug, or malformed field |
| 401 | Missing or invalid API key |
| 404 | No such link or page (also returned for links you do not own) |
| 405 | Wrong HTTP method for that path |
| 429 | Rate limit exceeded — check the Retry-After header |
| 500 | Something broke on our side |