Files
tgex-frontend/API_DOCS.md
2025-12-29 10:12:13 +03:00

526 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TGEX Backend API v2
## Аутентификация
**JWT Bearer Token** в заголовке `Authorization: Bearer <token>`
### Получение токена через Telegram Bot
Логика точно такая же как и раньше
### Эндпоинты
| Метод | Эндпоинт | Описание | Auth |
|-------|----------|----------|------|
| `GET` | `/auth/complete` | Обмен временного токена на JWT | ❌ |
| `GET` | `/auth/me` | Получить текущего пользователя | ✅ |
**Response** `/auth/me`:
```json
{
"id": "uuid",
"telegram_id": 123456789,
"username": "string | null"
}
```
---
## Workspaces (Рабочие пространства)
Воркспейсы - изолированные пространства для команд. У пользователя может быть несколько воркспейсов.
| Метод | Эндпоинт | Описание |
|-------|----------|----------|
| `GET` | `/workspaces` | Список воркспейсов пользователя (пагинация) |
| `POST` | `/workspaces` | Создать воркспейс |
| `PATCH` | `/workspaces/{workspace_id}` | Обновить название |
| `DELETE` | `/workspaces/{workspace_id}` | Удалить воркспейс |
**Body** `POST /workspaces`:
```json
{
"name": "string"
}
```
**Response**:
```json
{
"id": "uuid",
"name": "string"
}
```
---
## Workspace Members (Участники воркспейса)
| Метод | Эндпоинт | Описание |
|-------|----------|----------|
| `GET` | `/workspaces/{workspace_id}/members` | Список участников (пагинация) |
| `PUT` | `/workspaces/{workspace_id}/members/{user_id}/permissions` | Обновить права участника |
**Права доступа** (`PermissionKey`):
- `admin_full` - полный доступ
- `projects_read` - чтение проектов
- `projects_write` - запись проектов
- `placements_read` - чтение размещений
- `placements_write` - запись размещений
- `analytics_read` - чтение аналитики
**Scope types**: `project` (ограничение прав на конкретный проект)
**Body** `PUT permissions`:
```json
{
"permissions": [
{
"key": "admin_full"
},
{
"key": "projects_write",
"scopes": [
{"type": "project", "id": "project-uuid"}
]
}
]
}
```
---
## Workspace Invites (Приглашения)
| Метод | Эндпоинт | Описание |
|-------|----------|----------|
| `GET` | `/workspaces/{workspace_id}/invites` | Список приглашений (пагинация) |
| `POST` | `/workspaces/{workspace_id}/invites` | Создать приглашение |
**Body** `POST /invites`:
```json
{
"username": "telegram_username" // без @
}
```
**Статусы приглашения**: `PENDING`, `ACCEPTED`, `REJECTED`
---
## Projects (Проекты / Целевые каналы)
Проекты = целевые Telegram каналы, которые продвигаются. Создаются через Telegram бота.
| Метод | Эндпоинт | Описание |
|-------|----------|----------|
| `GET` | `/workspaces/{workspace_id}/projects` | Список проектов (пагинация) |
**Response**:
```json
{
"id": "uuid",
"telegram_id": -1001234567890,
"title": "string",
"username": "string | null",
"status": "ACTIVE | INACTIVE | ARCHIVED"
}
```
**Управление проектами**: через Telegram бота (добавить/удалить канал)
---
## Channels (Каналы для размещений)
Каталог Telegram каналов, где можно размещать рекламу.
| Метод | Эндпоинт | Описание | Фильтры |
|-------|----------|----------|---------|
| `GET` | `/channels` | Список каналов (пагинация) | `?username=...` |
**Response**:
```json
{
"id": "uuid",
"telegram_id": -1002345678901,
"title": "string",
"username": "string | null",
"description": "string | null",
"subscribers_count": 15000
}
```
---
## Purchase Plan (План закупа)
План закупа - список каналов для покупки рекламы в рамках проекта.
| Метод | Эндпоинт | Описание |
|-------|----------|----------|
| `GET` | `/workspaces/{ws}/projects/{proj}/purchase-plan/channels` | Список каналов плана (пагинация) |
| `POST` | `/workspaces/{ws}/projects/{proj}/purchase-plan/channels` | Добавить канал в план |
| `PATCH` | `/workspaces/{ws}/projects/{proj}/purchase-plan/channels/{id}` | Обновить параметры канала |
| `DELETE` | `/workspaces/{ws}/projects/{proj}/purchase-plan/channels/{id}` | Удалить из плана |
**Body** `POST`:
```json
{
"channel_id": "uuid",
"planned_date": "2025-01-15T12:00:00Z", // optional
"price": 5000.50, // optional
"comment": "string" // optional
}
```
**Body** `PATCH`:
```json
{
"planned_date": "2025-01-15T12:00:00Z", // optional
"price": 5000.50, // optional
"comment": "string" // optional
}
```
**Response**:
```json
{
"id": "uuid",
"status": "PLANNED | COMPLETED | CANCELLED",
"planned_date": "2025-01-15T12:00:00Z | null",
"price": 5000.50,
"comment": "string | null",
"channel": {
"id": "uuid",
"title": "string",
"username": "string | null",
"subscribers_count": 15000
}
}
```
---
## Creatives (Креативы)
Креативы = рекламные материалы (текст с пригласительной ссылкой).
| Метод | Эндпоинт | Описание | Фильтры |
|-------|----------|----------|---------|
| `GET` | `/workspaces/{ws}/creatives` | Список креативов (пагинация) | `?project_id=...&include_archived=false` |
| `GET` | `/workspaces/{ws}/creatives/{id}` | Один креатив | |
| `POST` | `/workspaces/{ws}/creatives?project_id=...` | Создать креатив | |
| `PATCH` | `/workspaces/{ws}/creatives/{id}` | Обновить креатив | |
| `DELETE` | `/workspaces/{ws}/creatives/{id}` | Удалить (архивировать) | |
**Body** `POST/PATCH`:
```json
{
"name": "string",
"text": "Текст с {invite_link} тегом"
}
```
**Response**:
```json
{
"id": "uuid",
"name": "string",
"text": "string",
"status": "ACTIVE | ARCHIVED",
"placements_count": 5
}
```
**Важно**: `{invite_link}` в тексте заменяется на уникальную ссылку при создании размещения.
---
## Placements (Размещения)
Размещения = факт размещения креатива в канале.
| Метод | Эндпоинт | Описание | Фильтры |
|-------|----------|----------|---------|
| `GET` | `/workspaces/{ws}/placements` | Список размещений (пагинация) | `?project_id=...&placement_channel_id=...&creative_id=...&include_archived=false` |
| `GET` | `/workspaces/{ws}/placements/{id}` | Одно размещение | |
| `POST` | `/workspaces/{ws}/placements` | Создать размещение | |
| `PATCH` | `/workspaces/{ws}/placements/{id}` | Обновить размещение | |
| `DELETE` | `/workspaces/{ws}/placements/{id}` | Удалить (архивировать) | |
**Body** `POST`:
```json
{
"project_id": "uuid",
"placement_channel_id": "uuid",
"creative_id": "uuid",
"placement_date": "2025-01-15T12:00:00Z",
"cost": 5000.50, // optional
"comment": "string", // optional
"ad_post_url": "https://t.me/channel/123", // optional
"invite_link_type": "PUBLIC | APPROVAL"
}
```
**Body** `PATCH`:
```json
{
"placement_date": "2025-01-15T12:00:00Z", // optional
"cost": 5000.50, // optional
"comment": "string", // optional
"ad_post_url": "https://t.me/channel/123" // optional
}
```
**Response**:
```json
{
"id": "uuid",
"placement_date": "2025-01-15T12:00:00Z",
"cost": 5000.50,
"comment": "string | null",
"ad_post_url": "string | null",
"invite_link_type": "PUBLIC | APPROVAL",
"invite_link": "https://t.me/+UniqueCode",
"status": "ACTIVE | ARCHIVED",
"subscriptions_count": 42,
"views_count": 1850,
"views_availability": "UNKNOWN | AVAILABLE | UNAVAILABLE | MANUAL",
"last_views_fetch_at": "2025-01-15T14:30:00Z",
"project": {
"id": "uuid",
"title": "string",
"username": "string | null"
},
"placement_channel": {
"id": "uuid",
"title": "string",
"username": "string | null",
"subscribers_count": 15000
},
"creative": {
"id": "uuid",
"name": "string"
}
}
```
**Типы пригласительных ссылок**:
- `PUBLIC` - открытая ссылка
- `APPROVAL` - с одобрением через бота
**Статус просмотров**:
- `UNKNOWN` - еще не проверялось
- `AVAILABLE` - просмотры доступны (автообновление)
- `UNAVAILABLE` - нет доступа к просмотрам
- `MANUAL` - ручной ввод
---
## Views History (История просмотров)
| Метод | Эндпоинт | Описание | Фильтры |
|-------|----------|----------|---------|
| `GET` | `/workspaces/{ws}/placements/{id}/views/history` | История просмотров (пагинация) | `?from_date=...&to_date=...` |
**Response**:
```json
{
"id": "uuid",
"views_count": 1850,
"fetched_at": "2025-01-15T14:30:00Z"
}
```
---
## Analytics (Аналитика)
Все эндпоинты поддерживают фильтр `?project_id=...` для конкретного проекта.
### Аналитика размещений
| Метод | Эндпоинт | Описание |
|-------|----------|----------|
| `GET` | `/workspaces/{ws}/analytics/placements` | Аналитика по размещениям (пагинация) |
**Response**:
```json
{
"placement_id": "uuid",
"placement_channel_title": "string",
"placement_channel_username": "string | null",
"creative_name": "string",
"placement_date": "2025-01-15T12:00:00Z",
"cost": 5000.50,
"subscriptions_count": 42,
"views_count": 1850,
"cps": 119.05, // cost per subscription
"cpm": 2702.70 // cost per mille views
}
```
### Аналитика креативов
| Метод | Эндпоинт | Описание |
|-------|----------|----------|
| `GET` | `/workspaces/{ws}/analytics/creatives` | Аналитика по креативам (пагинация) |
**Response**:
```json
{
"creative_id": "uuid",
"creative_name": "string",
"placements_count": 5,
"total_cost": 25000.00,
"total_subscriptions": 210,
"total_views": 9250,
"avg_cps": 119.05,
"avg_cpm": 2702.70
}
```
### Аналитика каналов
| Метод | Эндпоинт | Описание |
|-------|----------|----------|
| `GET` | `/workspaces/{ws}/analytics/channels` | Аналитика по каналам (пагинация) |
**Response**:
```json
{
"channel_id": "uuid",
"channel_title": "string",
"channel_username": "string | null",
"placements_count": 3,
"total_cost": 15000.00,
"total_subscriptions": 126,
"total_views": 5550,
"avg_cps": 119.05,
"avg_cpm": 2702.70
}
```
### Аналитика расходов
| Метод | Эндпоинт | Описание | Фильтры |
|-------|----------|----------|---------|
| `GET` | `/workspaces/{ws}/analytics/spending` | Динамика расходов | `?date_from=...&date_to=...&grouping=DAY\|WEEK\|MONTH` |
**Response**:
```json
{
"items": [
{
"date": "2025-01-15",
"cost": 5000.50,
"subscriptions": 42,
"views": 1850
}
],
"total_cost": 25000.00,
"total_subscriptions": 210,
"total_views": 9250
}
```
**Группировка** (`DateGrouping`): `DAY`, `WEEK`, `MONTH`
---
## Пагинация
Все эндпоинты с пагинацией возвращают:
```json
{
"items": [...],
"total": 42,
"page": 1,
"size": 50,
"pages": 1
}
```
**Query параметры**: `?page=1&size=50`
---
## Статусы и Enum
### WorkspaceUserStatus
- `ACTIVE` - активный участник
- `INVITED` - приглашён, но не принял
### WorkspaceInviteStatus
- `PENDING` - ожидает принятия
- `ACCEPTED` - принято
- `REJECTED` - отклонено
### ProjectStatus / ChannelStatus
- `ACTIVE` - активен
- `INACTIVE` - неактивен
- `ARCHIVED` - архивирован
### CreativeStatus / PlacementStatus
- `ACTIVE` - активен
- `ARCHIVED` - архивирован
### PurchasePlanStatus
- `PLANNED` - запланирован
- `COMPLETED` - завершён
- `CANCELLED` - отменён
### InviteLinkType
- `PUBLIC` - открытая ссылка
- `APPROVAL` - с одобрением бота
### PostViewsAvailability
- `UNKNOWN` - неизвестно (ещё не проверялось)
- `AVAILABLE` - доступны (автообновление)
- `UNAVAILABLE` - недоступны
- `MANUAL` - ручной ввод
---
## Коды ошибок HTTP
- `200` - OK
- `201` - Created
- `204` - No Content (успешное удаление)
- `400` - Bad Request (валидация)
- `401` - Unauthorized (нет токена)
- `403` - Forbidden (нет прав)
- `404` - Not Found
- `500` - Internal Server Error
**Формат ошибки**:
```json
{
"detail": "Error message"
}
```
---
## Особенности
1. **Все UUID в формате**: `xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx`
2. **Даты в ISO 8601**: `2025-01-15T12:00:00Z` (UTC)
3. **Метрики автообновляются**: просмотры обновляются воркером каждые 60 секунд (если `views_availability = AVAILABLE`)
4. **Подписки отслеживаются**: через Telegram бота при присоединении по invite_link
5. **Права проверяются**: все эндпоинты под воркспейсами требуют соответствующих прав
6. **Soft delete**: удаление = архивирование (статус `ARCHIVED`)
---
## Telegram Bot Integration
- Создание проектов (добавление целевых каналов)
- Создание креативов через диалог
- Приглашения в воркспейсы
- Отслеживание подписок через invite links
- Начальная аутентификация (`/start` → временный токен)