API: Ссылки
Эндпоинты для работы с трекинговыми ссылками.
Создать ссылку
POST /api/linksBody:
{
"url": "https://example.com",
"title": "Мой пост",
"utm_source": "telegram",
"utm_medium": "post",
"utm_campaign": "promo",
"tagIds": [1, 2],
"starts_at": "2026-05-01T10:00:00Z",
"expires_at": "2026-12-31T23:59:59Z",
"expired_url": "https://example.com/expired",
"max_clicks": 1000,
"password": "secret",
"ios_url": "https://apps.apple.com/...",
"android_url": "https://play.google.com/...",
"desktop_url": "https://example.com/desktop",
"pixelIds": [1],
"webhook_url": "https://example.com/webhook",
"webhook_method": "POST"
}Обязательное поле — url. Все остальные опциональны.
| Поле | Тип | Описание |
|---|---|---|
starts_at | ISO 8601 | Дата начала действия. До этой даты посетитель увидит страницу с обратным отсчётом. |
expires_at | ISO 8601 | Дата истечения. После неё ссылка перестаёт работать. |
expired_url | URL | Куда перенаправить после истечения или исчерпания лимита. |
max_clicks | число | Максимум переходов. После достижения — ссылка блокируется. |
webhook_url | URL | URL для отправки данных о кликах (webhook). |
webhook_method | строка | Метод отправки: GET или POST. По умолчанию POST. |
INFO
starts_at должна быть в будущем. Если указаны и starts_at, и expires_at, дата начала должна быть раньше даты истечения.
Ответ:
{
"id": 1,
"code": "x7k2m1",
"trackingUrl": "https://tgio.app/x7k2m1",
"original_url": "https://example.com",
"title": "Мой пост"
}Редактировать ссылку
PATCH /api/links/:idПозволяет изменить параметры ссылки без смены короткого кода.
Body (все поля опциональны):
{
"url": "https://example.com/new",
"title": "Новый заголовок",
"utm_source": "telegram",
"utm_medium": "post",
"utm_campaign": "promo2",
"tagIds": [1, 3],
"starts_at": "2026-06-01T10:00:00Z",
"expires_at": "2026-12-31T23:59:59Z",
"expired_url": "https://example.com/expired",
"max_clicks": 2000,
"password": "new-secret",
"ios_url": "https://apps.apple.com/...",
"android_url": "https://play.google.com/...",
"desktop_url": "https://example.com/desktop",
"pixelIds": [2],
"domain_id": 1,
"webhook_url": "https://example.com/webhook",
"webhook_method": "POST",
"webhook_enabled": true,
"is_active": true
}Чтобы удалить значение, передайте null (например, "webhook_url": null).
Ответ: аналогичен ответу создания ссылки (с trackingUrl).
Получить ссылку
GET /api/links/:idВозвращает полную информацию о ссылке.
Ответ:
{
"id": 1,
"code": "x7k2m1",
"original_url": "https://example.com",
"title": "Мой пост",
"trackingUrl": "https://tgio.app/x7k2m1",
"webhook_url": "https://example.com/webhook",
"webhook_method": "POST",
"webhook_enabled": true,
"webhook_failures": 0
}Webhooks
При каждом клике по ссылке с настроенным webhook, система отправляет данные на указанный URL.
Payload (POST)
{
"event": "click",
"link": {
"id": 1,
"code": "x7k2m1",
"original_url": "https://example.com",
"title": "Мой пост"
},
"click": {
"ip": "203.0.113.1",
"country": "RU",
"city": "Moscow",
"device_type": "mobile",
"os": "Android",
"browser": "Chrome",
"referer": "https://t.me/...",
"is_bot": false,
"is_unique": true,
"clicked_at": "2025-01-15T10:30:00.000Z"
}
}При методе GET данные передаются как query-параметры.
Валидация
При добавлении webhook (создание или редактирование ссылки) система отправляет тестовый запрос. Webhook считается валидным, если сервер отвечает статусом 200 или 201.
Повторные попытки
Если webhook не отвечает или возвращает ошибку, система повторяет запрос до 5 раз с нарастающими интервалами (0, 2, 5, 15, 30 секунд).
Автоотключение
После 100 неудачных отправок webhook автоматически отключается (webhook_enabled = false). Пользователь может повторно включить его через редактирование ссылки.
Массовое создание (bulk)
POST /api/links/bulkBody:
{
"urls": ["https://example.com/page1", "https://example.com/page2", "https://example.com/page3"]
}| Поле | Тип | Описание |
|---|---|---|
urls | string[] | Массив URL-адресов (от 1 до 100). Протокол обязателен. |
Каждая ссылка создаётся с доменом по умолчанию. Если лимит тарифа позволяет создать только часть ссылок, будут созданы первые N в пределах лимита.
Ответ:
{
"created": 2,
"errors": 1,
"results": [
{ "url": "https://example.com/page1", "trackingUrl": "https://tgio.app/ab12cd", "code": "ab12cd", "id": 1 },
{ "url": "https://example.com/page2", "trackingUrl": "https://tgio.app/ef34gh", "code": "ef34gh", "id": 2 }
],
"failed": [{ "url": "https://example.com/page3", "error": "Duplicate URL" }]
}Через бота
Вы также можете отправить боту сообщение с несколькими URL — он автоматически создаст трекинговую ссылку для каждого.
Список ссылок
GET /api/links?tags=1,2Query параметры: tags — ID тегов через запятую (опционально)
Ответ:
[
{
"id": 1,
"code": "x7k2m1",
"original_url": "https://example.com",
"title": "Мой пост",
"stats": { "totalClicks": 42, "uniqueClicks": 38, "botClicks": 4 }
}
]Статистика ссылки
GET /api/links/:id/stats?period=7dQuery параметры: period — 1d | 7d | 30d | 90d | 1y | all
Ответ:
{
"totalClicks": 42,
"uniqueClicks": 38,
"botClicks": 4,
"avgClicksPerDay": 6,
"topCountry": "RU"
}Клики
GET /api/links/:id/clicks?page=1&limit=50Query параметры: page (по умолчанию 1), limit (по умолчанию 50, макс. 100)
Ответ:
{
"data": [
{
"id": 1,
"clicked_at": "2025-01-15T10:30:00Z",
"country": "RU",
"city": "Moscow",
"device": "mobile",
"browser": "Chrome",
"os": "Android",
"referer": "https://t.me/...",
"is_bot": false
}
],
"total": 42,
"page": 1,
"limit": 50
}География
GET /api/links/:id/geo?period=7dОтвет:
[
{ "country": "RU", "count": 25, "percentage": 59.5 },
{ "country": "UA", "count": 10, "percentage": 23.8 }
]Устройства
GET /api/links/:id/devices?period=7dОтвет:
{
"devices": [
{ "name": "mobile", "count": 30, "percentage": 71.4 },
{ "name": "desktop", "count": 12, "percentage": 28.6 }
],
"browsers": [{ "name": "Chrome", "count": 20, "percentage": 47.6 }],
"os": [{ "name": "Android", "count": 18, "percentage": 42.9 }]
}График по времени
GET /api/links/:id/timeline?period=7d&granularity=daily&tz=Europe/MoscowQuery параметры: period, granularity (hourly | daily), tz (таймзона, опционально)
Ответ:
[
{ "date": "2025-01-15", "clicks": 12, "unique": 10 },
{ "date": "2025-01-16", "clicks": 8, "unique": 7 }
]Боты
GET /api/links/:id/bots?period=7dОтвет:
{
"totalBots": 4,
"botPercentage": 9.5,
"bots": [
{ "name": "Googlebot", "count": 2 },
{ "name": "YandexBot", "count": 1 }
]
}Тепловая карта
GET /api/links/:id/heatmap?period=30d&tz=Europe/MoscowОтвет:
[
{ "day": 0, "hour": 14, "count": 5 },
{ "day": 1, "hour": 10, "count": 3 }
]day: 0 = Воскресенье, 6 = Суббота. hour: 0–23.
Отправить сводку в бот
POST /api/links/send-summaryBody:
{
"period": "7d",
"linkId": 1
}Если linkId указан — отправляет PNG-изображение со статистикой конкретной ссылки. Без linkId — общую сводку по всем ссылкам.
Также поддерживаются поля dateFrom и dateTo (ISO-строки) для произвольного диапазона дат.
Ответ:
{ "ok": true }Поделиться QR-кодом
POST /api/links/:id/share-qrBody:
{
"qrImage": "<base64 PNG>"
}Отправляет QR-код ссылки как изображение в бот-чат.
Ответ:
{ "ok": true }Для всех эндпоинтов используйте заголовок Authorization: Bearer <token>.
Экспорт кликов
POST /api/links/:id/exportBody:
{
"format": "csv",
"period": "7d"
}| Параметр | Тип | Описание |
|---|---|---|
format | csv | xlsx | pdf | Обязательный. Формат файла |
period | string | Необязательный. Фильтр по периоду |
Формирует файл с данными о кликах и отправляет его в чат с Telegram-ботом.
Ответ:
{
"ok": true,
"message": "Файл будет отправлен в чат с ботом",
"rows": 1542
}Файл содержит колонки: Дата, IP, Страна, Город, Устройство, ОС, Браузер, Реферер, Бот, Имя бота, Уникальный. Максимум 10 000 записей за один экспорт.
