Blame
|
1 | # **Открытый программный интерфейс (Open API v2.0)** |
||||||
| 2 | ||||||||
| 3 | Система спутникового мониторинга транспорта SKIF.PRO имеет открытое API для интеграции телематических данных и аналитики в любые сторонние корпоративные системы: 1С:Предприятие (УАТ, ERP), TMS/WMS логистические платформы, BI-системы и мобильные приложения. |
|||||||
| 4 | ||||||||
| 5 | Интерактивное описание API и документация доступны по адресу: [https://api.skif.pro](https://api.skif.pro) (Swagger UI: [https://api.skif.pro/docs](https://api.skif.pro/docs)). |
|||||||
| 6 | ||||||||
| 7 | Для выполнения интеграционных запросов и работы фоновых служб рекомендуется явно использовать выделенный рабочий сервер: **[https://app1.skif.pro/api_v1](https://app1.skif.pro/api_v1)**. |
|||||||
| 8 | ## **Быстрые ссылки для разработчиков** |
|||||||
| 9 | ||||||||
| 10 | | Ресурс | Описание | Ссылка | |
|||||||
| 11 | |:---|:---|:---| |
|||||||
| 12 | | **Портал API** | Официальный портал открытого программного интерфейса | [api.skif.pro](https://api.skif.pro) | |
|||||||
| 13 | | **Swagger UI** | Интерактивная веб-песочница с описанием методов и возможностью тестирования | [api.skif.pro/docs](https://api.skif.pro/docs) | |
|||||||
| 14 | | **Рабочий сервер API** | Рекомендуемый выделенный/резервный контур для интеграций и фоновых задач | `https://app1.skif.pro/api_v1` | |
|||||||
| 15 | | **Postman-коллекция** | Готовая коллекция эндпоинтов со схемой переменных и примерами запросов | [Скачать коллекцию Postman v2.1](https://api.skif.pro/postman/SKIF_Platform_API_v2.json) | |
|||||||
| 16 | | **OpenAPI 3.0 JSON** | Машиночитаемая спецификация для генерации клиентских библиотек (SDK) | [api.skif.pro/openapi.json](https://api.skif.pro/openapi.json) | |
|||||||
| 17 | ||||||||
| 18 | --- |
|||||||
| 19 | ||||||||
| 20 | ## **Быстрый старт: первые данные за 3 шага** |
|||||||
| 21 | ||||||||
| 22 | Для отправки запросов используется базовый адрес: `https://app1.skif.pro/api_v1`. |
|||||||
| 23 | ||||||||
| 24 | ### **Шаг 1. Авторизация и получение токена** |
|||||||
| 25 | ||||||||
| 26 | Аутентификация в API выполняется запросом `POST /api_v1/login`: |
|||||||
| 27 | ||||||||
| 28 | ```bash |
|||||||
| 29 | curl -i -X POST "https://app1.skif.pro/api_v1/login" \ |
|||||||
| 30 | -H "Content-Type: application/json" \ |
|||||||
| 31 | -d '{ |
|||||||
| 32 | "userProviderId": "your_login@company.ru", |
|||||||
| 33 | "provider_key": "EMAIL", |
|||||||
| 34 | "password": "your_password" |
|||||||
| 35 | }' |
|||||||
| 36 | ``` |
|||||||
| 37 | ||||||||
| 38 | > **Важно**: При успешной авторизации (`HTTP 200`) тело ответа пустое, а токен авторизации возвращается **в HTTP-заголовке ответа**: |
|||||||
| 39 | > `Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9...` |
|||||||
| 40 | ||||||||
| 41 | --- |
|||||||
| 42 | ||||||||
| 43 | ### **Шаг 2. Первый запрос: Список объектов компании** |
|||||||
| 44 | ||||||||
| 45 | Для всех последующих запросов передавайте полученный токен в заголовке `Authorization: Bearer <токен>`. **Использование сессионных cookies не требуется — API работает автономно по Bearer-токену.** |
|||||||
| 46 | ||||||||
| 47 | ```bash |
|||||||
| 48 | curl -X POST "https://app1.skif.pro/api_v1/units/list" \ |
|||||||
| 49 | -H "Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9..." \ |
|||||||
| 50 | -H "Content-Type: application/json" \ |
|||||||
| 51 | -d '{ |
|||||||
| 52 | "from": 0, |
|||||||
| 53 | "count": 10 |
|||||||
| 54 | }' |
|||||||
| 55 | ``` |
|||||||
| 56 | ||||||||
| 57 | **Пример ответа сервера:** |
|||||||
| 58 | ```json |
|||||||
| 59 | { |
|||||||
| 60 | "max": 42, |
|||||||
| 61 | "list": [ |
|||||||
| 62 | { |
|||||||
| 63 | "id": "3efbec79-a0b2-41aa-a859-cacd80323d2f", |
|||||||
| 64 | "name": "Газель Next А102ВВ", |
|||||||
| 65 | "device_type": "Navtelecom SMART S-2420", |
|||||||
| 66 | "imei": "866795031900671" |
|||||||
| 67 | } |
|||||||
| 68 | ] |
|||||||
| 69 | } |
|||||||
| 70 | ``` |
|||||||
| 71 | ||||||||
| 72 | --- |
|||||||
| 73 | ||||||||
| 74 | ### **Шаг 3. Запрос телеметрии и текущего состояния ТС** |
|||||||
| 75 | ||||||||
| 76 | Получение актуальных параметров объекта (координаты, скорость, зажигание, датчики уровня топлива): |
|||||||
| 77 | ||||||||
| 78 | ```bash |
|||||||
| 79 | curl -X GET "https://app1.skif.pro/api_v1/units?ids=3efbec79-a0b2-41aa-a859-cacd80323d2f" \ |
|||||||
| 80 | -H "Authorization: Bearer <токен>" |
|||||||
| 81 | ``` |
|||||||
| 82 | ||||||||
| 83 | --- |
|||||||
| 84 | ||||||||
| 85 | ## **Постоянный API-ключ компании (Static API Key)** |
|||||||
| 86 | ||||||||
| 87 | Если вашей интеграции (например, серверу 1С или регулярному фоновому скрипту) неудобно регулярно вызывать логин и хранить динамические JWT-токены, администратор компании может выпустить постоянный токен доступа. |
|||||||
| 88 | ||||||||
| 89 | 1. **Создание постоянного ключа** (выполняет администратор через API или веб-кабинет): |
|||||||
| 90 | ```bash |
|||||||
| 91 | POST https://app1.skif.pro/api_v1/users/:user_id/create_token |
|||||||
| 92 | { |
|||||||
| 93 | "valid_to": "2028-12-31 23:59:59" |
|||||||
| 94 | } |
|||||||
| 95 | ``` |
|||||||
| 96 | В ответе возвращается ключ: `{"user_company_api_key": "YOUR_COMPANY_API_KEY"}`. |
|||||||
| 97 | ||||||||
| 98 | 2. **Использование ключа**: |
|||||||
| 99 | Передавайте данный ключ в любом запросе в заголовке `user_company_api_key`: |
|||||||
| 100 | ```bash |
|||||||
| 101 | curl -X POST "https://app1.skif.pro/api_v1/units/list" \ |
|||||||
| 102 | -H "user_company_api_key: YOUR_COMPANY_API_KEY" \ |
|||||||
| 103 | -H "Content-Type: application/json" \ |
|||||||
| 104 | -d '{"from": 0, "count": 10}' |
|||||||
| 105 | ``` |
|||||||
| 106 | ## **Основные функциональные модули API** |
|||||||
| 107 | ||||||||
| 108 | | Модуль | Ключевые методы | Возможности и типовые задачи | |
|||||||
| 109 | |:---|:---|:---| |
|||||||
| 110 | | **Объекты и датчики** | `POST /units/list`<br>`GET /units?ids=...`<br>`GET /unit_sensors/:id` | Реестр транспортных средств компании, установленные терминалы, счетчики пробега/моточасов, тарировочные таблицы баков. | |
|||||||
| 111 | | **Пользователи и водители** | `POST /users/query`<br>`POST /users`<br>`POST /drivers/import_csv`<br>`POST /users/import_csv`<br>`PATCH /users/roles/bulk` | Справочник пользователей и водителей компании: фильтр по признаку водителя и ролям, быстрое создание водителя по ФИО, пакетный импорт водителей и пользователей из CSV, массовая смена роли. Водители используются для автоназначения на объекты по коду (RFID). | |
|||||||
| 112 | | **Телеметрия и треки** | `POST /fasttracks`<br>`POST /fasttracks/bulk`<br>`GET /box_tracks` | Получение детализированных треков за интервал дат, сглаживание выбросов GPS, чтение сырых пакетов телеметрии. | |
|||||||
| 113 | | **Поездки и стоянки** | `POST /report` (Шаблон «Поездки»)<br>`POST /chronology_report` | Детектор движения: расчет поездок, пробега, остановок и стоянок с определением адресов стоянок. | |
|||||||
| 114 | | **Контроль топлива** | `POST /report` (Шаблон «Топливо»)<br>`GET /units/fuel_level` | Расход топлива по ДУТ и CAN-шине, детекция сливов и заправок с точным объемом в литрах. | |
|||||||
| 115 | | **Геозоны и маршруты** | `GET /geozones`<br>`POST /geozones`<br>`POST /races/list` | Контроль входа/выхода из полигонов и окружностей, плановые маршруты и контроль соблюдения графика. | |
|||||||
| 116 | | **События и тревоги** | `POST /events/list`<br>`POST /notifications` | Тревоги по превышению скорости, кнопке SOS, эвакуации, отключению питания трекера. Доставка через Webhooks / Telegram. | |
|||||||
| 117 | | **Аналитические отчеты** | `POST /report`<br>`POST /report_excel` | Сводные ведомости по парку за период, экспорт готовых отчетов в Excel (`.xlsx`) и PDF. | |
|||||||
| 118 | | **Интеграция с 1С** | `POST /units/list`<br>`POST /report` | Заполнение путевых листов 1С фактическим пробегом, расходом ГСМ и отработанными моточасами. | |
|||||||
| 119 | ## **Стандарты взаимодействия, ограничения и производительность** |
|||||||
| 120 | ||||||||
| 121 | ### **Выбор сервера** |
|||||||
| 122 | - **Рабочий контур для интеграций (рекомендуется)**: `https://app1.skif.pro/api_v1`. |
|||||||
| 123 | Использование сервера `app1.skif.pro` обеспечивает прямое и стабильное обслуживание API-интеграций и фоновых задач без конкуренции за пул сетевых соединений основного клиентского интерфейса. |
|||||||
| 124 | - **Интерактивная документация**: `https://api.skif.pro` (Swagger: `https://api.skif.pro/docs`). |
|||||||
| 125 | - **Тестовый контур**: `https://release.skif.pro/api_v1`. |
|||||||
| 126 | ||||||||
| 127 | ### **Лимиты частоты запросов (Rate Limits)** |
|||||||
| 128 | В сервисе авторизации платформы (`skif_auth`) действует автоматическая защита от перегрузки: |
|||||||
| 129 | - **Базовый лимит**: **40 запросов в минуту** на учетную запись (по скользящему окну 60 секунд на каждый шаблон маршрута). |
|||||||
| 130 | - **Лимит на метод `/login`**: до **40 запросов в минуту** с одного IP-адреса. |
|||||||
| 131 | - **Код ответа при превышении лимита**: сервер возвращает `HTTP 429 Too Many Requests` со структурой: |
|||||||
| 132 | ```json |
|||||||
| 133 | { |
|||||||
| 134 | "code": 4029, |
|||||||
| 135 | "field": "", |
|||||||
| 136 | "message": "Превышено количество отправленных запросов в минуту, подождите немного." |
|||||||
| 137 | } |
|||||||
| 138 | ``` |
|||||||
| 139 | ||||||||
| 140 | ### **Рекомендации по паузам между запросами (Throttling)** |
|||||||
| 141 | 1. **Интервал 300–600 мс**: После выполнения каждого запроса в цикле рекомендуется выдерживать паузу **300–600 мс** перед отправкой следующего вызова (особенно для ресурсоемких операций: выгрузка треков `POST /fasttracks`, расчет отчетов `POST /report`, построение хронологии `POST /chronology_report` или опрос расширенных данных по ТС). Это предотвращает случайное исчерпание лимита в 40 запросов в минуту и исключает взаимные блокировки при параллельной обработке. |
|||||||
| 142 | 2. **Пакетная обработка (`bulk`)**: Вместо последовательного опроса каждого транспортного средства по отдельности используйте пакетные методы (например, `POST /fasttracks` поддерживает массив идентификаторов `units: [{"id": "..."}, ...]`). |
|||||||
| 143 | 3. **Обработка ошибки 429**: При получении ответа `429` скрипт интеграции должен сделать экспоненциальную паузу (backoff) на 2–5 секунд перед повтором запроса. |
|||||||
| 144 | ||||||||
| 145 | --- |
|||||||
| 146 | ||||||||
| 147 | ## **Примеры кода** |
|||||||
| 148 | ||||||||
| 149 | ### **Python: Получение списка ТС с обработкой пауз** |
|||||||
| 150 | ||||||||
| 151 | ```python |
|||||||
| 152 | import time |
|||||||
| 153 | import requests |
|||||||
| 154 | ||||||||
| 155 | # Рекомендуемый сервер для API интеграций |
|||||||
| 156 | BASE_URL = "https://app1.skif.pro/api_v1" |
|||||||
| 157 | ||||||||
| 158 | # 1. Авторизация |
|||||||
| 159 | auth_resp = requests.post( |
|||||||
| 160 | f"{BASE_URL}/login", |
|||||||
| 161 | json={ |
|||||||
| 162 | "userProviderId": "your_login@company.ru", |
|||||||
| 163 | "provider_key": "EMAIL", |
|||||||
| 164 | "password": "your_password" |
|||||||
| 165 | }, |
|||||||
| 166 | headers={"Content-Type": "application/json"} |
|||||||
| 167 | ) |
|||||||
| 168 | auth_resp.raise_for_status() |
|||||||
| 169 | ||||||||
| 170 | # 2. Извлечение токена из заголовка ответа |
|||||||
| 171 | token = auth_resp.headers.get("Authorization") |
|||||||
| 172 | headers = { |
|||||||
| 173 | "Authorization": token, |
|||||||
| 174 | "Content-Type": "application/json", |
|||||||
| 175 | "Accept": "application/json" |
|||||||
| 176 | } |
|||||||
| 177 | ||||||||
| 178 | # 3. Запрос списка транспортных средств |
|||||||
| 179 | resp = requests.post( |
|||||||
| 180 | f"{BASE_URL}/units/list", |
|||||||
| 181 | headers=headers, |
|||||||
| 182 | json={"from": 0, "count": 20} |
|||||||
| 183 | ) |
|||||||
| 184 | resp.raise_for_status() |
|||||||
| 185 | ||||||||
| 186 | data = resp.json() |
|||||||
| 187 | print(f"Всего объектов в парке: {data.get('max')}") |
|||||||
| 188 | ||||||||
| 189 | for unit in data.get("list", []): |
|||||||
| 190 | unit_id = unit["id"] |
|||||||
| 191 | unit_name = unit["name"] |
|||||||
| 192 | print(f"• ТС: {unit_name} (ID: {unit_id})") |
|||||||
| 193 | ||||||||
| 194 | # Пауза 400-500 мс перед следующим тяжелым запросом телеметрии |
|||||||
| 195 | time.sleep(0.5) |
|||||||
| 196 | ||||||||
| 197 | telemetry_resp = requests.get( |
|||||||
| 198 | f"{BASE_URL}/units?ids={unit_id}", |
|||||||
| 199 | headers=headers |
|||||||
| 200 | ) |
|||||||
| 201 | if telemetry_resp.status_code == 200: |
|||||||
| 202 | telemetry = telemetry_resp.json() |
|||||||
| 203 | print(" Данные получены успешно.") |
|||||||
| 204 | elif telemetry_resp.status_code == 429: |
|||||||
| 205 | print(" Внимание: сработал лимит частоты, пауза 3 сек...") |
|||||||
| 206 | time.sleep(3) |
|||||||
| 207 | ``` |
|||||||
| 208 | ||||||||
| 209 | ### **Node.js / JavaScript (Fetch API с паузой)** |
|||||||
| 210 | ||||||||
| 211 | ```javascript |
|||||||
| 212 | // Рекомендуемый сервер для API интеграций |
|||||||
| 213 | const BASE_URL = 'https://app1.skif.pro/api_v1'; |
|||||||
| 214 | ||||||||
| 215 | // Функция задержки между вызовами (300-600 мс) |
|||||||
| 216 | const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); |
|||||||
| 217 | ||||||||
| 218 | async function runIntegration() { |
|||||||
| 219 | // 1. Авторизация |
|||||||
| 220 | const loginRes = await fetch(`${BASE_URL}/login`, { |
|||||||
| 221 | method: 'POST', |
|||||||
| 222 | headers: { 'Content-Type': 'application/json' }, |
|||||||
| 223 | body: JSON.stringify({ |
|||||||
| 224 | userProviderId: 'your_login@company.ru', |
|||||||
| 225 | provider_key: 'EMAIL', |
|||||||
| 226 | password: 'your_password' |
|||||||
| 227 | }) |
|||||||
| 228 | }); |
|||||||
| 229 | ||||||||
| 230 | if (!loginRes.ok) throw new Error(`Login failed with status: ${loginRes.status}`); |
|||||||
| 231 | ||||||||
| 232 | // Токен передается в HTTP-заголовке Authorization |
|||||||
| 233 | const token = loginRes.headers.get('authorization'); |
|||||||
| 234 | ||||||||
| 235 | // 2. Получение списка ТС |
|||||||
| 236 | const listRes = await fetch(`${BASE_URL}/units/list`, { |
|||||||
| 237 | method: 'POST', |
|||||||
| 238 | headers: { |
|||||||
| 239 | 'Authorization': token, |
|||||||
| 240 | 'Content-Type': 'application/json' |
|||||||
| 241 | }, |
|||||||
| 242 | body: JSON.stringify({ from: 0, count: 10 }) |
|||||||
| 243 | }); |
|||||||
| 244 | ||||||||
| 245 | const listData = await listRes.json(); |
|||||||
| 246 | console.log(`Всего объектов: ${listData.max}`); |
|||||||
| 247 | ||||||||
| 248 | for (const unit of listData.list) { |
|||||||
| 249 | console.log(`Объект: ${unit.name} (ID: ${unit.id})`); |
|||||||
| 250 | ||||||||
| 251 | // Пауза 500 мс перед следующим запросом |
|||||||
| 252 | await sleep(500); |
|||||||
| 253 | ||||||||
| 254 | const unitRes = await fetch(`${BASE_URL}/units?ids=${unit.id}`, { |
|||||||
| 255 | headers: { 'Authorization': token } |
|||||||
| 256 | }); |
|||||||
| 257 | ||||||||
| 258 | if (unitRes.status === 429) { |
|||||||
| 259 | console.warn('Превышен лимит запросов, пауза 3 сек...'); |
|||||||
| 260 | await sleep(3000); |
|||||||
| 261 | } |
|||||||
| 262 | } |
|||||||
| 263 | } |
|||||||
| 264 | ||||||||
| 265 | runIntegration().catch(console.error); |
|||||||
| 266 | ``` |
|||||||
| 267 | ## **Безопасность и лучшие практики** |
|||||||
| 268 | ||||||||
| 269 | 1. **Защита учетных данных**: Не храните логин и пароль в открытом виде в исходном коде. Используйте переменные окружения или постоянный ключ `user_company_api_key`. |
|||||||
| 270 | 2. **Кэширование токена**: Полученный JWT-токен действителен длительное время. Не вызывайте метод `/login` перед каждым отдельным запросом — сохраняйте полученный токен и обновляйте его только при ответе сервера `401 Unauthorized`. |
|||||||
| 271 | 3. **Учет лимитов и таймаутов**: При интеграции с 1С настраивайте таймаут ожидания HTTP-соединения не менее 30–60 секунд для тяжелых аналитических отчетов и используйте интервалы 300–600 мс между последовательными запросами. |
|||||||
| 272 | ## **Техническая поддержка интеграторов и обратная связь** |
|||||||
| 273 | ||||||||
| 274 | Если вы обнаружили ошибку в работе методов, расхождение с документацией или у вас возник технический вопрос по интеграции: |
|||||||
| 275 | ||||||||
| 276 | 1. **Форма обратной связи на портале API**: Нажмите кнопку **«Сообщить об ошибке»** в шапке документации [https://api.skif.pro](https://api.skif.pro). Заполните контур проблемы (боевой `app1.skif.pro` или стенд документации `api.skif.pro`), метод и ваш API-ключ компании. Обращение сразу поступит в очередь разработки. |
|||||||
| 277 | 2. **Email техподдержки**: [support@skif.pro](mailto:support@skif.pro) (обязательно укажите тему вида `[API Issue] {Метод} - {Компания}`, ваш `company_id` и cURL вызова). |
|||||||
| 278 | 3. **Персональный менеджер**: Обратитесь к вашему персональному менеджеру SKIF.PRO для согласования индивидуальных лимитов или выделенных вычислительных очередей. |
|||||||