feat: global platform v2 update
This commit is contained in:
525
API_DOCS.md
Normal file
525
API_DOCS.md
Normal file
@@ -0,0 +1,525 @@
|
||||
# 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` → временный токен)
|
||||
|
||||
Reference in New Issue
Block a user