Files
tgex-frontend/API_DOCUMENTATION.md
2025-11-10 12:07:24 +03:00

11 KiB
Raw Blame History

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?: string
  • external_channel_id?: string
  • creative_id?: string
  • is_archived?: boolean
  • date_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?: string
  • date_from?: string
  • date_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?: string
  • date_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?: string
  • date_from?: string
  • date_to?: string
  • type: '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?: string
  • date_from?: string
  • date_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 - 401
  • FORBIDDEN - 403
  • NOT_FOUND - 404
  • VALIDATION_ERROR - 422
  • INTERNAL_ERROR - 500
  • CHANNEL_NOT_FOUND - 404
  • CHANNEL_ALREADY_EXISTS - 409
  • INSUFFICIENT_PERMISSIONS - 403
  • CREATIVE_IN_USE - 409
  • INVALID_INVITE_LINK - 422