A REST API to create short links and read analytics. Easy to integrate from any language — just send your API key.
Authorization.curl -X POST https://link.tj/api/v1/links \
-H "Authorization: Bearer lnktj_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/a/very/long/link"}'Every request must include the header Authorization: Bearer <key> (or X-Api-Key: <key>). Base URL:
https://link.tj/api/v1Keys are tied to your account, so the same plan limits apply as in the UI. CORS is open (*); the API can be called from the browser.
Conditions & requirements
Mobile and native apps obtain a token with email and password: POST /api/auth/token. The response contains a JWT that you pass to /api/v1/* exactly like an API key: Authorization: Bearer <token>. If 2FA is enabled, include a code field; without it the endpoint returns 401 with error: needs_2fa.
/api/auth/tokenEmail/password login → JWT for /api/v1/*. Body: email, password, code? (for 2FA).
How to use: Send email and password to obtain a JWT for the app.
curl -X POST https://link.tj/api/auth/token \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com","password":"••••••••"}'Response
{
"token": "eyJhbGciOi...",
"user": { "id": "clx...", "email": "you@example.com", "name": "You", "role": "USER" }
}Conditions & requirements
/api/v1/meAccount, plan and monthly usage.
How to use: Request your profile, plan and current-month usage.
curl https://link.tj/api/v1/me \
-H "Authorization: Bearer lnktj_API_KEY"Response
{
"data": {
"email": "you@example.com",
"plan": { "name": "Free", "linkLimit": 5, "clickLimit": 1000 },
"usage": { "linksUsed": 2, "linksRemaining": 3, "clicksUsed": 87 }
}
}Conditions & requirements
/api/v1/linksCreate a short link. Fields: url (required for kind=url), slug (optional), title (optional), kind (optional: url | wifi | vcard | text), payload (object for non-url kinds).
wifi/vcard/text kinds require a paid plan (otherwise 403). Such a QR points to a tracked page /l/{slug}.
How to use: Send JSON with a url field (classic link) or kind + payload (typed link).
curl -X POST https://link.tj/api/v1/links \
-H "Authorization: Bearer lnktj_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com","slug":"promo","title":"Promo"}'Example: Wi-Fi (paid plan)
curl -X POST https://link.tj/api/v1/links \
-H "Authorization: Bearer lnktj_API_KEY" \
-H "Content-Type: application/json" \
-d '{"kind":"wifi","title":"Guest Wi-Fi","payload":{"ssid":"MyNet","encryption":"WPA","password":"secret123"}}'Response 201
{
"data": {
"id": "clx...",
"slug": "promo",
"shortUrl": "https://link.tj/promo",
"kind": "url",
"originalUrl": "https://example.com",
"summary": null,
"clicks": 0
},
"usage": { "linksUsed": 3, "linkLimit": 5, "linksRemaining": 2 }
}Response 402 — plan limit reached
{
"error": "limit_reached",
"code": "limit_reached",
"recommend": { "name": "Core", "priceMonthly": 8, "linkLimit": 100 }
}Conditions & requirements
/api/v1/linksA list of your links. Parameters: limit (1–100), offset.
How to use: Fetch your links with pagination.
curl "https://link.tj/api/v1/links?limit=20&offset=0" \
-H "Authorization: Bearer lnktj_API_KEY"Response — list
{
"total": 42,
"limit": 20,
"offset": 0,
"data": [
{ "id": "clx...", "slug": "promo", "shortUrl": "https://link.tj/promo", "kind": "url",
"originalUrl": "https://example.com", "clicks": 128, "isActive": true }
]
}Conditions & requirements
/api/v1/links/{id_or_slug}Link details and click analytics (by country, device, source).
How to use: Pass a link id or slug to get its details and click analytics.
curl https://link.tj/api/v1/links/promo \
-H "Authorization: Bearer lnktj_API_KEY"Response — details & analytics
{
"data": {
"id": "clx...", "slug": "promo", "shortUrl": "https://link.tj/promo",
"originalUrl": "https://example.com", "clicks": 128, "isActive": true,
"analytics": {
"byCountry": [ { "name": "TJ", "count": 80 }, { "name": "RU", "count": 48 } ],
"byDevice": [ { "name": "mobile", "count": 95 }, { "name": "desktop", "count": 33 } ],
"byReferrer": [ { "name": "t.me", "count": 60 }, { "name": "Unknown", "count": 68 } ]
}
}
}Conditions & requirements
/api/v1/links/{id_or_slug}Delete a link and its analytics.
How to use: Pass an id or slug to delete the link.
curl -X DELETE https://link.tj/api/v1/links/promo \
-H "Authorization: Bearer lnktj_API_KEY"Conditions & requirements
Register a URL in the “Webhooks” section of your dashboard — we POST to your server when an event fires. Body: { event, data, ts }. Headers: X-LinkTJ-Event and X-LinkTJ-Signature.
How to use: Add a URL and subscribe to events in the “Webhooks” section, then verify the signature on your server.
link.created — link.created — a short link was created. data: { id, slug, url }.subscription.created — subscription.created — a subscription was started or renewed. data: { plan, amount, interval }.POST https://your-server.example/webhook
X-LinkTJ-Event: link.created
X-LinkTJ-Signature: <hmac-sha256-hex>
Content-Type: application/json
{ "event": "link.created", "data": { "id": "clx...", "slug": "promo", "url": "https://example.com" }, "ts": "2026-01-01T12:00:00.000Z" }The X-LinkTJ-Signature header is an HMAC-SHA256 of the raw request body signed with your webhook secret (whsec_…). Compare it to verify the request really came from link.tj.
Conditions & requirements
An external scheduler can trigger subscription renewals and weekly reports by passing the secret: ?secret=<CRON_SECRET>. The task parameter accepts renew, weekly or all (default all).
How to use: Point an external scheduler at the endpoint with the secret.
/api/cron?secret=&task=renew|weekly|allcurl -X POST "https://link.tj/api/cron?secret=CRON_SECRET&task=renew"Conditions & requirements
| 200 / 201 | Success |
| 400 | Bad request (e.g. invalid URL or slug) |
| 401 | Missing or invalid API key |
| 402 | Plan limit reached — upgrade required |
| 403 | Forbidden (e.g. wifi/vcard/text link types on the Free plan) |
| 404 | Link not found |
| 409 | Slug already taken |
| 429 | Too many requests — rate limit hit |