11 KiB
API Документация
Базовый URL
https://api.tgex.app/v1
Аутентификация
Все запросы (кроме /auth/*) требуют JWT токен в заголовке:
Authorization: Bearer <token>
1. Аутентификация
POST /auth/init
Инициализация процесса авторизации через Telegram
Response:
{
bot_username: string;
start_param: string; // "login"
}
POST /auth/complete
Завершение авторизации с одноразовым токеном
Request:
{
token: string; // one-time token from bot
}
Response:
{
access_token: string;
refresh_token: string;
user: User;
}
POST /auth/refresh
Обновление access токена
Request:
{
refresh_token: string;
}
Response:
{
access_token: string;
}
GET /auth/me
Получение информации о текущем пользователе
Response:
User;
2. Типы данных
User
{
id: string;
telegram_id: number;
username: string | null;
first_name: string;
last_name: string | null;
created_at: string; // ISO 8601
}
TargetChannel
{
id: string;
telegram_id: number;
title: string;
username: string | null; // @channel_name
description: string | null;
is_active: boolean;
created_at: string;
updated_at: string;
// Stats
total_purchases: number;
total_subscriptions: number;
avg_cpf: number | null; // Average Cost Per Follower
}
ExternalChannel
{
id: string;
telegram_id: number | null;
title: string;
username: string | null;
link: string; // t.me link or custom
subscribers_count: number | null;
description: string | null;
created_at: string;
updated_at: string;
// Relations
target_channels: string[]; // IDs of target channels
// Stats
total_purchases: number;
avg_cpf: number | null;
avg_cpm: number | null;
}
Creative
{
id: string;
name: string;
text: string; // Template with {link} placeholder
target_channel_id: string;
is_archived: boolean;
created_at: string;
updated_at: string;
// Relations
target_channel: TargetChannel;
// Stats
total_purchases: number;
total_subscriptions: number;
avg_cpf: number | null;
}
Purchase
{
id: string;
target_channel_id: string;
external_channel_id: string;
creative_id: string;
// Purchase details
scheduled_date: string | null; // ISO 8601
actual_date: string | null;
cost: number | null; // in rubles
comment: string | null;
post_link: string | null; // Link to ad post in external channel
invite_link: string; // Generated invite link
invite_link_type: "public" | "private"; // with bot approval or not
is_archived: boolean;
created_at: string;
updated_at: string;
// Relations
target_channel: TargetChannel;
external_channel: ExternalChannel;
creative: Creative;
// Stats
subscriptions_count: number;
views_count: number | null;
cpf: number | null; // Cost Per Follower
cpm: number | null; // Cost Per Mile (1000 views)
conversion_rate: number | null; // subscriptions / views * 100
}
Subscription
{
id: string;
purchase_id: string;
telegram_user_id: number;
username: string | null;
joined_at: string; // ISO 8601
event_type: "chat_member" | "join_request";
}
ViewsSnapshot
{
id: string;
purchase_id: string;
views: number;
fetched_at: string; // ISO 8601
}
3. Целевые каналы
GET /target-channels
Получение списка целевых каналов
Query params:
is_active?: boolean- фильтр по активности
Response:
{
data: TargetChannel[];
total: number;
}
GET /target-channels/:id
Получение детальной информации о канале
Response:
TargetChannel & {
recent_purchases: Purchase[]; // last 5
stats_by_period: {
period: 'day' | 'week' | 'month';
subscriptions: number;
cost: number;
cpf: number;
}[];
}
PATCH /target-channels/:id
Обновление канала (только is_active)
Request:
{
is_active: boolean;
}
Response:
TargetChannel;
DELETE /target-channels/:id
Отключение канала (soft delete)
Response:
{
success: true;
}
4. Внешние каналы
GET /external-channels
Получение списка внешних каналов
Query params:
target_channel_id?: string- фильтр по целевому каналуsearch?: string- поиск по названию/username
Response:
{
data: ExternalChannel[];
total: number;
}
GET /external-channels/:id
Получение детальной информации
Response:
ExternalChannel & {
purchases: Purchase[];
}
POST /external-channels
Создание нового внешнего канала
Request:
{
title: string;
username?: string;
link: string;
subscribers_count?: number;
description?: string;
target_channel_ids: string[]; // Привязка к целевым каналам
}
Response:
ExternalChannel;
PATCH /external-channels/:id
Обновление внешнего канала
Request:
Partial<{
title: string;
username: string;
link: string;
subscribers_count: number;
description: string;
target_channel_ids: string[];
}>;
Response:
ExternalChannel;
DELETE /external-channels/:id
Удаление внешнего канала
Response:
{
success: true;
}
POST /external-channels/import
Импорт из Excel (Tgstat)
Request:
Content-Type: multipart/form-data
file: File (Excel)
target_channel_id: string
Response:
{
imported: number;
skipped: number;
errors: string[];
channels: ExternalChannel[];
}
5. Креативы
GET /creatives
Получение списка креативов
Query params:
target_channel_id?: string- фильтр по целевому каналуis_archived?: boolean- фильтр по архивности
Response:
{
data: Creative[];
total: number;
}
GET /creatives/:id
Получение детальной информации
Response:
Creative & {
purchases: Purchase[];
}
POST /creatives
Создание нового креатива
Request:
{
name: string;
text: string; // Must contain {link} placeholder
target_channel_id: string;
}
Response:
Creative;
PATCH /creatives/:id
Обновление креатива
Request:
Partial<{
name: string;
text: string;
is_archived: boolean;
}>;
Response:
Creative;
DELETE /creatives/:id
Удаление креатива (только если нет активных закупов)
Response:
{
success: true;
}
6. Закупы
GET /purchases
Получение списка закупов
Query params:
target_channel_id?: stringexternal_channel_id?: stringcreative_id?: stringis_archived?: booleandate_from?: string(ISO 8601)date_to?: string(ISO 8601)sort?: 'date' | 'cost' | 'cpf' | 'subscriptions'order?: 'asc' | 'desc'
Response:
{
data: Purchase[];
total: number;
}
GET /purchases/:id
Получение детальной информации о закупе
Response:
Purchase & {
subscriptions: Subscription[];
views_history: ViewsSnapshot[];
}
POST /purchases
Создание нового закупа
Request:
{
target_channel_id: string;
external_channel_id: string;
creative_id: string;
scheduled_date?: string;
actual_date?: string;
cost?: number;
comment?: string;
post_link?: string;
invite_link_type: 'public' | 'private';
}
Response:
Purchase & {
formatted_message: string; // Creative text with invite_link inserted
}
PATCH /purchases/:id
Обновление закупа
Request:
Partial<{
scheduled_date: string;
actual_date: string;
cost: number;
comment: string;
post_link: string;
is_archived: boolean;
}>;
Response:
Purchase;
DELETE /purchases/:id
Удаление закупа
Response:
{
success: true;
}
POST /purchases/:id/refresh-views
Принудительное обновление просмотров
Response:
{
views: number;
fetched_at: string;
}
7. Аналитика
GET /analytics/overview
Общая статистика
Query params:
target_channel_id?: stringdate_from?: stringdate_to?: string
Response:
{
total_purchases: number;
total_cost: number;
total_subscriptions: number;
avg_cpf: number;
avg_cpm: number;
avg_conversion_rate: number;
}
GET /analytics/costs
Данные для графика затрат
Query params:
target_channel_id?: stringdate_from: string(required)date_to: string(required)group_by: 'day' | 'week' | 'month' | 'quarter' | 'year'
Response:
{
data: {
period: string; // ISO 8601 date (start of period)
cost: number;
purchases_count: number;
subscriptions: number;
}
[];
}
GET /analytics/channels
Аналитика по каналам
Query params:
target_channel_id?: stringdate_from?: stringdate_to?: stringtype: 'external' | 'target'
Response:
{
data: {
channel_id: string;
channel_name: string;
purchases_count: number;
total_cost: number;
total_subscriptions: number;
avg_cpf: number;
avg_cpm: number;
}
[];
}
GET /analytics/creatives
Аналитика по креативам
Query params:
target_channel_id?: stringdate_from?: stringdate_to?: string
Response:
{
data: {
creative_id: string;
creative_name: string;
purchases_count: number;
total_cost: number;
total_subscriptions: number;
avg_cpf: number;
conversion_rate: number;
}
[];
}
8. Коды ошибок
{
error: {
code: string;
message: string;
details?: any;
}
}
Основные коды:
UNAUTHORIZED- 401FORBIDDEN- 403NOT_FOUND- 404VALIDATION_ERROR- 422INTERNAL_ERROR- 500CHANNEL_NOT_FOUND- 404CHANNEL_ALREADY_EXISTS- 409INSUFFICIENT_PERMISSIONS- 403CREATIVE_IN_USE- 409INVALID_INVITE_LINK- 422