11 KiB
11 KiB
API и интеграция
🌐 Базовая информация
Базовый URL: https://corp.robotail.pro
API версия: v1
Протоколы:
- REST API -
https://corp.robotail.pro/api/v1/ - WebSocket -
wss://corp.robotail.pro/ws
🔐 Аутентификация
Получение токена
POST /api/auth/token/
Content-Type: application/json
{
"email": "user@example.com",
"password": "password"
}
Ответ:
{
"access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Обновление токена
POST /api/auth/token/refresh/
Content-Type: application/json
{
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Ответ:
{
"access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Использование токена
Все защищенные endpoints требуют Bearer токен в заголовке:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
👥 REST API - Пользователи
Получить список всех сотрудников
GET /api/v1/employees/
Authorization: Bearer {access_token}
Ответ:
[
{
"id": 1,
"username": "ivan_ivanov",
"email": "ivan@company.com",
"firstName": "Иван",
"lastName": "Иванов",
"department": "IT",
"position": "Разработчик",
"isOnline": true,
"avatarUrl": null
},
{
"id": 2,
"username": "maria_petrova",
"email": "maria@company.com",
"firstName": "Мария",
"lastName": "Петрова",
"department": "HR",
"position": "Менеджер",
"isOnline": false,
"avatarUrl": null
}
]
Получить текущего пользователя
GET /api/v1/employees/me/
Authorization: Bearer {access_token}
Ответ:
{
"id": 1,
"username": "ivan_ivanov",
"email": "ivan@company.com",
"firstName": "Иван",
"lastName": "Иванов",
"department": "IT",
"position": "Разработчик",
"isOnline": true,
"avatarUrl": null
}
Поиск пользователей
GET /api/v1/users/search/?q={query}
Authorization: Bearer {access_token}
Параметры:
q(string, required) - поисковый запрос (имя, отдел, должность)
Пример:
GET /api/v1/users/search/?q=Иван
Ответ:
[
{
"id": 1,
"username": "ivan_ivanov",
"firstName": "Иван",
"lastName": "Иванов",
"department": "IT",
"position": "Разработчик",
"isOnline": true
}
]
Обновить статус пользователя
PUT /api/v1/users/status/
Authorization: Bearer {access_token}
Content-Type: application/json
{
"isOnline": true
}
Ответ:
{
"success": true,
"message": "Статус обновлен"
}
💬 REST API - Сообщения
Получить все сообщения
GET /api/v1/messages/
Authorization: Bearer {access_token}
Ответ:
[
{
"id": 1,
"senderId": 2,
"senderName": "Мария Петрова",
"receiverId": 1,
"content": "Привет! Как дела?",
"timestamp": "2026-01-12T10:30:00Z",
"isRead": false
}
]
Получить сообщения с конкретным пользователем
GET /api/v1/messages/?user_id={userId}
Authorization: Bearer {access_token}
Параметры:
user_id(int, required) - ID пользователя для фильтрации
Пример:
GET /api/v1/messages/?user_id=2
Ответ:
[
{
"id": 1,
"senderId": 2,
"senderName": "Мария Петрова",
"receiverId": 1,
"content": "Привет!",
"timestamp": "2026-01-12T10:30:00Z",
"isRead": true
},
{
"id": 2,
"senderId": 1,
"senderName": "Иван Иванов",
"receiverId": 2,
"content": "Привет! Как дела?",
"timestamp": "2026-01-12T10:31:00Z",
"isRead": true
}
]
Отправить сообщение (REST fallback)
POST /api/v1/messages/
Authorization: Bearer {access_token}
Content-Type: application/json
{
"senderId": 1,
"receiverId": 2,
"content": "Текст сообщения"
}
Ответ:
{
"id": 3,
"senderId": 1,
"senderName": "Иван Иванов",
"receiverId": 2,
"content": "Текст сообщения",
"timestamp": "2026-01-12T10:35:00Z",
"isRead": false
}
🔌 WebSocket API
Подключение
URL: wss://corp.robotail.pro/ws
Поддерживаемые варианты URL:
wss://corp.robotail.pro/ws(основной)ws://corp.robotail.pro/ws(без SSL)wss://corp.robotail.pro/ws/(со слешем)wss://corp.robotail.pro/api/v1/wsws://corp.robotail.pro/api/v1/ws
WebSocketService автоматически пробует разные варианты и подключается к первому работающему
Обязательный заголовок:
Authorization: Bearer {access_token}
Пример подключения (C#):
var ws = new ClientWebSocket();
ws.Options.SetRequestHeader("Authorization", $"Bearer {accessToken}");
await ws.ConnectAsync(new Uri("wss://corp.robotail.pro/ws"), CancellationToken.None);
Формат сообщений
Все WebSocket сообщения имеют единый формат:
{
"type": "message_type",
"data": {
// данные специфичные для типа
}
}
Типы сообщений
1. Отправка сообщения (Client → Server)
{
"type": "message",
"data": {
"receiverId": 2,
"content": "Текст сообщения"
}
}
2. Получение сообщения (Server → Client)
{
"type": "message",
"data": {
"id": 456,
"senderId": 2,
"senderName": "Мария Петрова",
"receiverId": 1,
"content": "Текст сообщения",
"timestamp": "2026-01-12T10:30:00Z"
}
}
3. Индикатор набора текста (Client → Server)
{
"type": "typing",
"data": {
"recipientId": 2,
"isTyping": true
}
}
4. Индикатор набора текста (Server → Client)
{
"type": "typing",
"data": {
"senderId": 2,
"senderName": "Мария Петрова",
"isTyping": true
}
}
5. Обновление статуса пользователя (Server → Client)
{
"type": "user_status",
"data": {
"userId": 2,
"isOnline": true
}
}
Обработка событий (C#)
// Подписка на события
ServiceProvider.WebSocketService.MessageReceived += OnMessageReceived;
ServiceProvider.WebSocketService.UserStatusChanged += OnUserStatusChanged;
ServiceProvider.WebSocketService.TypingIndicatorReceived += OnTypingIndicator;
// Обработчики
private void OnMessageReceived(object sender, Message message)
{
// Обработка нового сообщения
}
private void OnUserStatusChanged(object sender, (int userId, bool isOnline) status)
{
// Обновление статуса пользователя в UI
}
private void OnTypingIndicator(object sender, (int userId, bool isTyping) typing)
{
// Показать/скрыть индикатор "печатает..."
}
🔄 Система управления токенами
Автоматическое обновление
ApiService автоматически управляет токенами:
-
При получении 401/403 ошибки:
- Пытается обновить access токен используя refresh токен
- Повторяет оригинальный запрос с новым токеном
- При неудаче перенаправляет на страницу входа
-
При успешном обновлении:
- Сохраняет новый access токен в SecureStorage
- Обновляет HTTP заголовки
- Возвращает результат оригинального запроса
-
При неудаче обновления:
- Очищает все токены
- Очищает SecureStorage
- Требует повторную аутентификацию
Хранение токенов
Токены хранятся в SecureStorage:
// Сохранение
await SecureStorage.SetAsync("access_token", accessToken);
await SecureStorage.SetAsync("refresh_token", refreshToken);
// Получение
var accessToken = await SecureStorage.GetAsync("access_token");
var refreshToken = await SecureStorage.GetAsync("refresh_token");
// Удаление
SecureStorage.Remove("access_token");
SecureStorage.Remove("refresh_token");
⚠️ Обработка ошибок
HTTP статус коды
- 200 OK - успешный запрос
- 201 Created - ресурс создан
- 400 Bad Request - неверные параметры запроса
- 401 Unauthorized - токен отсутствует или недействителен
- 403 Forbidden - доступ запрещен
- 404 Not Found - ресурс не найден
- 500 Internal Server Error - ошибка сервера
Формат ошибок
{
"error": "Описание ошибки",
"detail": "Детальная информация",
"code": "ERROR_CODE"
}
WebSocket коды закрытия
- 1000 - нормальное закрытие
- 1001 - сервер недоступен
- 1006 - аномальное закрытие (например, потеря сети)
- 1008 - нарушение политики (например, недействительный токен)
🔧 Конфигурация ApiService
var config = new ApiConfig
{
BaseUrl = "https://corp.robotail.pro/api",
TokenObtainPath = "/auth/token/",
TokenRefreshPath = "/auth/token/refresh/",
Timeout = 30,
DefaultHeaders = new Dictionary<string, string>
{
{ "Accept", "application/json" },
{ "Content-Type", "application/json" }
}
};
var apiService = new ApiService(config);
📝 Примечания
Лимиты и ограничения
- Максимальная длина сообщения: 4000 символов
- Rate limiting: 100 запросов в минуту на пользователя
- WebSocket idle timeout: 5 минут без активности
Рекомендации
- Приоритет WebSocket - используйте WebSocket для отправки сообщений, REST API только как fallback
- Переподключение - реализуйте автоматическое переподключение WebSocket при разрыве
- Кэширование - кэшируйте список пользователей для offline режима
- Optimistic UI - обновляйте UI сразу, не дожидаясь ответа сервера
Последнее обновление: 2026-01-12