Документация API

REST API для создания коротких ссылок и получения аналитики. Подходит для интеграции из любого языка — нужно лишь передать ваш API-ключ.

Быстрый старт

  1. Зарегистрируйтесь и откройте раздел API-ключи в кабинете.
  2. Создайте ключ и скопируйте его (он показывается один раз).
  3. Передавайте ключ в заголовке Authorization.
bash
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"}'

Аутентификация

Каждый запрос должен содержать заголовок Authorization: Bearer <key> (либо X-Api-Key: <key>). Базовый URL:

text
https://link.tj/api/v1

Ключи привязаны к вашему аккаунту, поэтому действуют те же лимиты тарифа, что и в интерфейсе. CORS открыт (*), API можно вызывать из браузера.

Условия и требования

  • Нужен аккаунт на link.tj и созданный API-ключ (раздел «API-ключи»).
  • Ключ показывается один раз — сохраните его сразу.
  • Передавайте заголовок Authorization: Bearer <key> или X-Api-Key: <key>.
  • Действуют лимиты вашего тарифа.
  • Ограничение частоты: 120 запросов в минуту на ключ (иначе 429 с retryAfter).
  • CORS открыт (*) — API можно вызывать из браузера.

Аутентификация для приложений (мобильные)

Мобильные и нативные приложения получают токен по email и паролю: POST /api/auth/token. В ответ приходит JWT, который передаётся в /api/v1/* так же, как API-ключ: Authorization: Bearer <token>. Если включена 2FA, добавьте поле code; без кода вернётся 401 с error: needs_2fa.

POST/api/auth/token

Логин по email/паролю → JWT для /api/v1/*. Тело: email, password, code? (для 2FA).

Как использовать: Отправьте email и пароль, чтобы получить JWT для приложения.

bash
curl -X POST https://link.tj/api/auth/token \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com","password":"••••••••"}'

Ответ

json
{
  "token": "eyJhbGciOi...",
  "user": { "id": "clx...", "email": "you@example.com", "name": "You", "role": "USER" }
}

Условия и требования

  • email и пароль обязательны (иначе 400).
  • Аккаунт не должен быть заблокирован (иначе 403).
  • Если включена 2FA — добавьте поле code; без него 401 с error: needs_2fa.
  • Лимит: 30 попыток за 15 мин на IP и 10 на email (иначе 429).
  • Полученный JWT передавайте в /api/v1/* как Authorization: Bearer <token>.

Эндпоинты

GET/api/v1/me

Аккаунт, тариф и расход лимитов за месяц.

Как использовать: Запросите профиль, тариф и расход лимитов за текущий месяц.

bash
curl https://link.tj/api/v1/me \
  -H "Authorization: Bearer lnktj_API_KEY"

Ответ

json
{
  "data": {
    "email": "you@example.com",
    "plan": { "name": "Free", "linkLimit": 5, "clickLimit": 1000 },
    "usage": { "linksUsed": 2, "linksRemaining": 3, "clicksUsed": 87 }
  }
}

Условия и требования

  • Требуется действующий API-ключ или JWT.
  • Аккаунт не должен быть заблокирован.
  • Метод только GET — данные относятся к владельцу ключа.
POST/api/v1/links

Создать короткую ссылку. Поля: url (обязательно для kind=url), slug (необязательно), title (необязательно), kind (необязательно: url | wifi | vcard | text), payload (объект для типов кроме url).

Типы wifi/vcard/text доступны на платных тарифах (иначе 403). Такой QR ведёт на отслеживаемую страницу /l/{slug}.

Как использовать: Отправьте JSON с полем url (обычная ссылка) или kind + payload (типизированная).

bash
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"}'

Пример: Wi-Fi (платный тариф)

bash
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"}}'

Ответ 201

json
{
  "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 }
}

Ответ 402 — достигнут лимит тарифа

json
{
  "error": "limit_reached",
  "code": "limit_reached",
  "recommend": { "name": "Core", "priceMonthly": 8, "linkLimit": 100 }
}

Условия и требования

  • url обязателен и должен быть корректным http(s) при kind=url (иначе 400).
  • slug необязателен; если занят — 409, если пуст — сгенерируется автоматически.
  • kind: url | wifi | vcard | text (по умолчанию url).
  • Типы wifi/vcard/text требуют платного тарифа (иначе 403) и поля payload.
  • title необязателен, не длиннее 200 символов.
  • При достижении лимита ссылок тарифа возвращается 402 с рекомендованным тарифом.
GET/api/v1/links

Список ваших ссылок. Параметры: limit (1–100), offset.

Как использовать: Получите свои ссылки постранично.

bash
curl "https://link.tj/api/v1/links?limit=20&offset=0" \
  -H "Authorization: Bearer lnktj_API_KEY"

Ответ — список

json
{
  "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 }
  ]
}

Условия и требования

  • limit от 1 до 100 (по умолчанию 50).
  • offset ≥ 0 для пагинации.
  • Возвращаются только ссылки владельца ключа; поле total — общее количество.
GET/api/v1/links/{id_or_slug}

Детали ссылки и аналитика кликов (по странам, устройствам, источникам).

Как использовать: Передайте id или slug ссылки, чтобы получить детали и аналитику кликов.

bash
curl https://link.tj/api/v1/links/promo \
  -H "Authorization: Bearer lnktj_API_KEY"

Ответ — детали и аналитика

json
{
  "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 } ]
    }
  }
}

Условия и требования

  • Принимается как id, так и slug.
  • Ссылка должна принадлежать владельцу ключа (иначе 404).
  • В ответе блок analytics: разбивка по странам, устройствам и источникам.
DELETE/api/v1/links/{id_or_slug}

Удалить ссылку и её аналитику.

Как использовать: Передайте id или slug, чтобы удалить ссылку.

bash
curl -X DELETE https://link.tj/api/v1/links/promo \
  -H "Authorization: Bearer lnktj_API_KEY"

Условия и требования

  • Ссылка должна принадлежать владельцу ключа (иначе 404).
  • Удаление необратимо и удаляет связанную аналитику.

Вебхуки (исходящие события)

Подключите URL в разделе «Вебхуки» кабинета — мы будем отправлять POST-запрос на ваш сервер при наступлении события. Тело: { event, data, ts }. Заголовки: X-LinkTJ-Event и X-LinkTJ-Signature.

Как использовать: Добавьте URL и подпишитесь на события в разделе «Вебхуки», затем проверяйте подпись на своём сервере.

События

  • link.createdlink.created — создана короткая ссылка. data: { id, slug, url }.
  • subscription.createdsubscription.created — оформлена или продлена подписка. data: { plan, amount, interval }.
http
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" }

Заголовок X-LinkTJ-Signature — это HMAC-SHA256 от тела запроса, подписанный секретом вебхука (whsec_…). Сравните его, чтобы убедиться, что запрос пришёл от link.tj.

Условия и требования

  • URL должен быть публичным https — внутренние и локальные адреса запрещены (защита от SSRF).
  • Подпишитесь минимум на одно событие (link.created, subscription.created).
  • Проверяйте X-LinkTJ-Signature = HMAC-SHA256(тело запроса, секрет whsec_…).
  • Адрес перепроверяется при доставке (защита от DNS-rebinding); редиректы не выполняются.
  • Таймаут доставки — 5 секунд; отвечайте кодом 2xx.

Плановые задачи (cron)

Внешний планировщик может запускать продление подписок и еженедельные отчёты, передав секрет: ?secret=<CRON_SECRET>. Параметр task: renew, weekly или all (по умолчанию all).

Как использовать: Настройте внешний планировщик на вызов эндпоинта с секретом.

POST/api/cron?secret=&task=renew|weekly|all
bash
curl -X POST "https://link.tj/api/cron?secret=CRON_SECRET&task=renew"

Условия и требования

  • Передайте ?secret=<CRON_SECRET> (или вызовите из сессии суперадмина).
  • task: renew | weekly | all (по умолчанию all).
  • Метод GET или POST.

Коды ответов

200 / 201Успешно
400Некорректный запрос (например, неверный URL или slug)
401Отсутствует или неверный API-ключ
402Достигнут лимит тарифа — нужно повысить тариф
403Доступ запрещён (например, типы wifi/vcard/text на бесплатном тарифе)
404Ссылка не найдена
409Slug уже занят
429Слишком много запросов — сработал лимит частоты

Готовы начать?

Создайте бесплатный аккаунт и получите API-ключ за минуту.

Получить ключ