@hubex/mcp 0.5.0 → 0.5.20260909

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubex/mcp",
3
- "version": "0.5.0",
3
+ "version": "0.5.20260909",
4
4
  "type": "module",
5
5
  "description": "MCP server for managing HubEx test data (tasks, assets, companies, users) via the HubEx REST API",
6
6
  "author": "HubEx Team",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "openapi": "3.0.1",
3
3
  "info": {
4
- "title": "Authenticatin and authorization API for HubEx",
4
+ "title": "Authentication and authorization API for HubEx",
5
5
  "description": "Performs all of the operations, necessary to authenticate and authorize a user as a valid tenant member. Offers an API for registering, verifying e-mail, changing password, etc.",
6
6
  "contact": {
7
7
  "name": "SmartService Backend Team",
@@ -21,8 +21,32 @@
21
21
  "Accounts"
22
22
  ],
23
23
  "summary": "Приложения учетной записи",
24
- "description": "Поддерживает ограничение результата через заголовок `Range`.\r\n \r\n## Пример запроса:\r\n```text\r\nGET /Accounts/this/applications\r\nAuthorization: Bearer <access-token>\r\nRange: Offset=0; Fetch=25\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n[\r\n {\r\n \"client\": {\r\n \"id\": 1,\r\n \"uniqueClientIdentifier\": \"abc-123-def-456\",\r\n \"agent\": \"Android 14\",\r\n \"clientType\": { \"id\": 1, \"name\": \"Mobile\" }\r\n },\r\n \"application\": {\r\n \"id\": 2,\r\n \"name\": \"HubEx Mobile\",\r\n \"version\": \"3.5.0\"\r\n },\r\n \"pushToken\": \"fcm-token-xyz\",\r\n \"timestamp\": \"2026-08-21T08:00:00Z\"\r\n }\r\n]\r\n```\r\n \r\n## Пример успешного ответа (206):\r\nТело ответа имеет тот же формат, что и для `200`, но содержит только часть диапазона. Заголовок `Content-Range` указывает общее количество.\r\n \r\n## Негативные сценарии:\r\n- 204 NoContent: приложения не найдены.\r\n- 401 Unauthorized: отсутствует или некорректен Bearer-токен.\r\n- 403 Forbidden: недостаточно прав `AccountClientApplicationList`.",
24
+ "description": "Поддерживает ограничение результата через query-параметры `offset` и `fetch`.\r\n \r\n## Пример запроса:\r\n`GET /Accounts/this/applications?offset=0&fetch=25`\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n[\r\n {\r\n \"client\": {\r\n \"id\": 1,\r\n \"uniqueClientIdentifier\": \"abc-123-def-456\",\r\n \"agent\": \"Android 14\",\r\n \"clientType\": { \"id\": 1, \"name\": \"Mobile\" }\r\n },\r\n \"application\": {\r\n \"id\": 2,\r\n \"name\": \"HubEx Mobile\",\r\n \"version\": \"3.5.0\"\r\n },\r\n \"pushToken\": \"fcm-token-xyz\",\r\n \"timestamp\": \"2026-08-21T08:00:00Z\"\r\n }\r\n]\r\n```\r\n \r\n## Пример успешного ответа (206):\r\nТело ответа имеет тот же формат, что и для `200`, но содержит только часть диапазона. Заголовок `Content-Range` указывает общее количество.\r\n \r\n## Негативные сценарии:\r\n- 204 NoContent: приложения не найдены.\r\n- 401 Unauthorized: отсутствует или некорректен Bearer-токен.\r\n- 403 Forbidden: недостаточно прав `AccountClientApplicationList`.",
25
25
  "parameters": [
26
+ {
27
+ "name": "Range",
28
+ "in": "header",
29
+ "description": "Формат: items=FROM-TILL , где FROM - начальный элемент (включая), TILL - конечный элемент (включая)",
30
+ "schema": {
31
+ "type": "string"
32
+ }
33
+ },
34
+ {
35
+ "name": "offset",
36
+ "in": "query",
37
+ "description": "количество элементов, которое нобходимо пропустить",
38
+ "schema": {
39
+ "type": "string"
40
+ }
41
+ },
42
+ {
43
+ "name": "fetch",
44
+ "in": "query",
45
+ "description": "количество элементов, которое необходимо вернуть",
46
+ "schema": {
47
+ "type": "string"
48
+ }
49
+ },
26
50
  {
27
51
  "name": "X-Application-ID",
28
52
  "in": "header",
@@ -130,7 +154,7 @@
130
154
  "Accounts"
131
155
  ],
132
156
  "summary": "Актуализация данных о приложениях текущей учетной записи",
133
- "description": "## Пример запроса:\r\n```json\r\nPUT /Accounts/this/applications\r\nAuthorization: Bearer <access-token>\r\n \r\n{\r\n \"clientTypeID\": 1,\r\n \"agent\": \"Android 14\",\r\n \"applicationVersion\": \"3.5.0\",\r\n \"pushToken\": \"fcm-token-xyz\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202):\r\nТело ответа пустое.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized: отсутствует идентификатор учётной записи и участника тенанта в токене.",
157
+ "description": "## Пример запроса:\r\n`PUT /Accounts/this/applications`\r\n \r\n```json\r\n{\r\n \"clientTypeID\": 1,\r\n \"agent\": \"Android 14\",\r\n \"applicationVersion\": \"3.5.0\",\r\n \"pushToken\": \"fcm-token-xyz\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202):\r\nТело ответа пустое.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized: отсутствует идентификатор учётной записи и участника тенанта в токене.",
134
158
  "parameters": [
135
159
  {
136
160
  "name": "X-Application-ID",
@@ -206,7 +230,7 @@
206
230
  "Accounts"
207
231
  ],
208
232
  "summary": "Отвязка приложения и устройства от текущей учетной записи",
209
- "description": "## Пример запроса:\r\n```json\r\nDELETE /Accounts/this/applications\r\nAuthorization: Bearer <access-token>\r\n \r\n{\r\n \"uniqueClientIdentifier\": \"abc-123-def-456\",\r\n \"applicationID\": 2\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202):\r\nТело ответа пустое.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized: отсутствует идентификатор учётной записи и участника тенанта в токене.",
233
+ "description": "## Пример запроса:\r\n`DELETE /Accounts/this/applications`\r\n \r\n```json\r\n{\r\n \"uniqueClientIdentifier\": \"abc-123-def-456\",\r\n \"applicationID\": 2\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202):\r\nТело ответа пустое.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized: отсутствует идентификатор учётной записи и участника тенанта в токене.",
210
234
  "parameters": [
211
235
  {
212
236
  "name": "X-Application-ID",
@@ -284,7 +308,7 @@
284
308
  "Accounts"
285
309
  ],
286
310
  "summary": "Выход из системы. Метод можно вызывать с просроченным токеном.",
287
- "description": "## Пример запроса:\r\n```json\r\nPOST /Accounts/logout\r\nAuthorization: Bearer <access-token>\r\n \r\n{\r\n \"uniqueClientIdentifier\": \"abc-123-def-456\",\r\n \"applicationID\": 2\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\nТело ответа пустое.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized: токен не содержит идентификатор учётной записи или участника тенанта.\r\n- 409 Conflict: отсутствует или некорректен заголовок Authorization, либо тело запроса не указано.",
311
+ "description": "## Пример запроса:\r\n`POST /Accounts/logout`\r\n \r\n```json\r\n{\r\n \"uniqueClientIdentifier\": \"abc-123-def-456\",\r\n \"applicationID\": 2\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\nТело ответа пустое.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized: токен не содержит идентификатор учётной записи или участника тенанта.\r\n- 409 Conflict: отсутствует или некорректен заголовок Authorization, либо тело запроса не указано.",
288
312
  "parameters": [
289
313
  {
290
314
  "name": "X-Application-ID",
@@ -357,7 +381,7 @@
357
381
  "Accounts"
358
382
  ],
359
383
  "summary": "Создаёт аккаунт с указанной электронной почтой (если ещё не создан),\r\nблокирует его по причине непройденной верификации почты и отправляет\r\nнотификацию для отправки письма или SMS со ссылкой для верификации.",
360
- "description": "## Пример запроса:\r\n```json\r\nPOST /Accounts/register\r\nAuthorization: Bearer <access-token>\r\n \r\n{\r\n \"email\": \"user%40example.com\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200) — существующая учётная запись:\r\n```json\r\n{\r\n \"id\": 1001,\r\n \"verificationRequestValidTill\": \"2026-08-21T12:00:00Z\",\r\n \"isEmailVerified\": false,\r\n \"isMobilePhoneVerified\": false,\r\n \"isPasswordDefined\": false,\r\n \"isNewAccount\": false\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202) — новая учётная запись (email или SMS):\r\n```json\r\n{\r\n \"id\": 1001,\r\n \"verificationRequestValidTill\": \"2026-08-21T12:00:00Z\",\r\n \"isEmailVerified\": false,\r\n \"isMobilePhoneVerified\": false,\r\n \"isPasswordDefined\": false,\r\n \"isNewAccount\": true\r\n}\r\n```\r\nОтправляется уведомление для верификации (письмо или SMS).\r\n \r\n## Пример успешного ответа (202) — новая учётная запись (domainLogin):\r\nТело ответа аналогично примеру выше с `\"isNewAccount\": true`. Уведомление **не отправляется**.\r\n \r\n## Негативные сценарии:\r\n- 409 Conflict: тело запроса не указано, ошибки валидации, не указаны email/телефон/domainLogin или указаны некорректные данные.",
384
+ "description": "## Пример запроса:\r\n`POST /Accounts/register`\r\n \r\n```json\r\n{\r\n \"email\": \"user%40example.com\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200) — существующая учётная запись:\r\n```json\r\n{\r\n \"id\": 1001,\r\n \"verificationRequestValidTill\": \"2026-08-21T12:00:00Z\",\r\n \"isEmailVerified\": false,\r\n \"isMobilePhoneVerified\": false,\r\n \"isPasswordDefined\": false,\r\n \"isNewAccount\": false\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202) — новая учётная запись (email или SMS):\r\n```json\r\n{\r\n \"id\": 1001,\r\n \"verificationRequestValidTill\": \"2026-08-21T12:00:00Z\",\r\n \"isEmailVerified\": false,\r\n \"isMobilePhoneVerified\": false,\r\n \"isPasswordDefined\": false,\r\n \"isNewAccount\": true\r\n}\r\n```\r\nОтправляется уведомление для верификации (письмо или SMS).\r\n \r\n## Пример успешного ответа (202) — новая учётная запись (domainLogin):\r\nТело ответа аналогично примеру выше с `\"isNewAccount\": true`. Уведомление **не отправляется**.\r\n \r\n## Негативные сценарии:\r\n- 409 Conflict: тело запроса не указано, ошибки валидации, не указаны email/телефон/domainLogin или указаны некорректные данные.",
361
385
  "parameters": [
362
386
  {
363
387
  "name": "X-Application-ID",
@@ -599,8 +623,32 @@
599
623
  "Accounts"
600
624
  ],
601
625
  "summary": "Список уведомлений из лога",
602
- "description": "Поддерживает ограничение результата через заголовок `Range`.\r\n \r\n## Пример запроса:\r\n```text\r\nGET /Accounts/this/notifications\r\nAuthorization: Bearer <access-token>\r\nRange: Offset=0; Fetch=25\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n[\r\n {\r\n \"notificationID\": 501,\r\n \"providerID\": 1,\r\n \"subject\": \"Подтверждение адреса электронной почты\",\r\n \"content\": \"Для подтверждения перейдите по ссылке...\",\r\n \"sent\": \"2026-08-21T08:01:00Z\"\r\n }\r\n]\r\n```\r\n \r\n## Пример успешного ответа (206):\r\nТело ответа имеет тот же формат, что и для `200`, но содержит только часть диапазона. Заголовок `Content-Range` указывает общее количество.\r\n \r\n## Негативные сценарии:\r\n- 204 NoContent: уведомления не найдены.\r\n- 401 Unauthorized: отсутствует или некорректен Bearer-токен.\r\n- 403 Forbidden: недостаточно прав `NotificationLogList`.",
626
+ "description": "Поддерживает ограничение результата через query-параметры `offset` и `fetch`.\r\n \r\n## Пример запроса:\r\n`GET /Accounts/this/notifications?offset=0&fetch=25`\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n[\r\n {\r\n \"notificationID\": 501,\r\n \"providerID\": 1,\r\n \"subject\": \"Подтверждение адреса электронной почты\",\r\n \"content\": \"Для подтверждения перейдите по ссылке...\",\r\n \"sent\": \"2026-08-21T08:01:00Z\"\r\n }\r\n]\r\n```\r\n \r\n## Пример успешного ответа (206):\r\nТело ответа имеет тот же формат, что и для `200`, но содержит только часть диапазона. Заголовок `Content-Range` указывает общее количество.\r\n \r\n## Негативные сценарии:\r\n- 204 NoContent: уведомления не найдены.\r\n- 401 Unauthorized: отсутствует или некорректен Bearer-токен.\r\n- 403 Forbidden: недостаточно прав `NotificationLogList`.",
603
627
  "parameters": [
628
+ {
629
+ "name": "Range",
630
+ "in": "header",
631
+ "description": "Формат: items=FROM-TILL , где FROM - начальный элемент (включая), TILL - конечный элемент (включая)",
632
+ "schema": {
633
+ "type": "string"
634
+ }
635
+ },
636
+ {
637
+ "name": "offset",
638
+ "in": "query",
639
+ "description": "количество элементов, которое нобходимо пропустить",
640
+ "schema": {
641
+ "type": "string"
642
+ }
643
+ },
644
+ {
645
+ "name": "fetch",
646
+ "in": "query",
647
+ "description": "количество элементов, которое необходимо вернуть",
648
+ "schema": {
649
+ "type": "string"
650
+ }
651
+ },
604
652
  {
605
653
  "name": "X-Application-ID",
606
654
  "in": "header",
@@ -710,7 +758,7 @@
710
758
  "Messages"
711
759
  ],
712
760
  "summary": "Отправляет письмо проверки почты на указанный адрес эл. почты (если не был указан, то на адрес уч.записи)",
713
- "description": "## Пример запроса:\r\n```json\r\nPOST /Messages/verifyEmail\r\nAuthorization: Bearer <access-token>\r\n \r\n{\r\n \"email\": \"user%40example.com\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202):\r\n```json\r\n{\r\n \"id\": 1001,\r\n \"isEmailVerified\": false,\r\n \"isPhoneVerified\": false,\r\n \"verificationRequestValidTill\": \"2026-08-21T12:00:00Z\",\r\n \"isPasswordDefined\": false,\r\n \"isNewAccount\": false,\r\n \"verificationCodeRepeatTimeout\": 60\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized: не указан идентификатор учётной записи (ни в токене, ни в теле запроса).\r\n- 204 NoContent: учётная запись не найдена.\r\n- 409 Conflict: указан некорректный адрес электронной почты.",
761
+ "description": "## Пример запроса:\r\n`POST /Messages/verifyEmail`\r\n \r\n```json\r\n{\r\n \"email\": \"user%40example.com\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202):\r\n```json\r\n{\r\n \"id\": 1001,\r\n \"isEmailVerified\": false,\r\n \"isPhoneVerified\": false,\r\n \"verificationRequestValidTill\": \"2026-08-21T12:00:00Z\",\r\n \"isPasswordDefined\": false,\r\n \"isNewAccount\": false,\r\n \"verificationCodeRepeatTimeout\": 60\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized: не указан идентификатор учётной записи (ни в токене, ни в теле запроса).\r\n- 204 NoContent: учётная запись не найдена.\r\n- 409 Conflict: указан некорректный адрес электронной почты.",
714
762
  "parameters": [
715
763
  {
716
764
  "name": "X-Application-ID",
@@ -803,7 +851,7 @@
803
851
  "Messages"
804
852
  ],
805
853
  "summary": "Отправляет SMS проверки номера телефона на указанный телефон (если не был указан, то на телефон учетной записи)",
806
- "description": "## Пример запроса:\r\n```json\r\nPOST /Messages/verifyPhone\r\nAuthorization: Bearer <access-token>\r\n \r\n{\r\n \"phone\": \"+79001234567\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202):\r\n```json\r\n{\r\n \"id\": 1001,\r\n \"isEmailVerified\": false,\r\n \"isPhoneVerified\": false,\r\n \"verificationRequestValidTill\": \"2026-08-21T12:00:00Z\",\r\n \"isPasswordDefined\": false,\r\n \"isNewAccount\": false,\r\n \"verificationCodeRepeatTimeout\": 60\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized: не указан идентификатор учётной записи (ни в токене, ни в теле запроса).\r\n- 204 NoContent: учётная запись не найдена.\r\n- 409 Conflict: указан некорректный номер телефона.",
854
+ "description": "## Пример запроса:\r\n`POST /Messages/verifyPhone`\r\n \r\n```json\r\n{\r\n \"phone\": \"+79001234567\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202):\r\n```json\r\n{\r\n \"id\": 1001,\r\n \"isEmailVerified\": false,\r\n \"isPhoneVerified\": false,\r\n \"verificationRequestValidTill\": \"2026-08-21T12:00:00Z\",\r\n \"isPasswordDefined\": false,\r\n \"isNewAccount\": false,\r\n \"verificationCodeRepeatTimeout\": 60\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized: не указан идентификатор учётной записи (ни в токене, ни в теле запроса).\r\n- 204 NoContent: учётная запись не найдена.\r\n- 409 Conflict: указан некорректный номер телефона.",
807
855
  "parameters": [
808
856
  {
809
857
  "name": "X-Application-ID",
@@ -896,7 +944,7 @@
896
944
  "Messages"
897
945
  ],
898
946
  "summary": "Отправляет запрос на изменение пароля на указанный адрес эл. почты; для аутентифицированного пользователя — на адрес эл. почты уч.записи",
899
- "description": "## Пример запроса:\r\n```json\r\nPOST /Messages/requestPasswordChange\r\n \r\n{\r\n \"credentials\": \"user%40example.com\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202):\r\n```json\r\n{\r\n \"id\": 1001,\r\n \"isEmailVerified\": true,\r\n \"isPhoneVerified\": false,\r\n \"verificationRequestValidTill\": \"2026-08-21T12:00:00Z\",\r\n \"isPasswordDefined\": true,\r\n \"isNewAccount\": false,\r\n \"verificationCodeRepeatTimeout\": 60\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized: учётная запись не найдена.\r\n- 409 Conflict: указаны некорректные credentials или восстановление недоступно для указанного типа учётных данных.",
947
+ "description": "## Пример запроса:\r\n`POST /Messages/requestPasswordChange`\r\n \r\n```json\r\n{\r\n \"credentials\": \"user%40example.com\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202):\r\n```json\r\n{\r\n \"id\": 1001,\r\n \"isEmailVerified\": true,\r\n \"isPhoneVerified\": false,\r\n \"verificationRequestValidTill\": \"2026-08-21T12:00:00Z\",\r\n \"isPasswordDefined\": true,\r\n \"isNewAccount\": false,\r\n \"verificationCodeRepeatTimeout\": 60\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized: учётная запись не найдена.\r\n- 409 Conflict: указаны некорректные credentials или восстановление недоступно для указанного типа учётных данных.",
900
948
  "parameters": [
901
949
  {
902
950
  "name": "X-Application-ID",
@@ -986,7 +1034,7 @@
986
1034
  "Passwords"
987
1035
  ],
988
1036
  "summary": "Изменяет пароль учётной записи.",
989
- "description": "## Пример запроса (по SMS-коду):\r\n```json\r\nPOST /Passwords/change\r\n \r\n{\r\n \"password\": \"MyNewP%40ssw0rd\",\r\n \"code\": \"123456\",\r\n \"mobilePhone\": \"+79001234567\"\r\n}\r\n```\r\n \r\n## Пример запроса (по текущему паролю):\r\n```json\r\nPOST /Passwords/change\r\nAuthorization: Bearer <access-token>\r\n \r\n{\r\n \"password\": \"MyNewP%40ssw0rd\",\r\n \"currentPassword\": \"OldP%40ssw0rd\"\r\n}\r\n```\r\n \r\n## Пример запроса (по хэшу из e-mail):\r\n```json\r\nPOST /Passwords/change\r\n \r\n{\r\n \"password\": \"MyNewP%40ssw0rd\",\r\n \"codeHash\": \"a1b2c3d4e5f6\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202):\r\nТело ответа пустое.\r\n \r\n## Негативные сценарии:\r\n- 403 Forbidden: указан `currentPassword`, но пользователь не аутентифицирован.\r\n- 409 Conflict: неверный текущий пароль или некорректный верификационный код.",
1037
+ "description": "## Пример запроса (по SMS-коду):\r\n`POST /Passwords/change`\r\n \r\n```json\r\n{\r\n \"password\": \"MyNewP%40ssw0rd\",\r\n \"code\": \"123456\",\r\n \"mobilePhone\": \"+79001234567\"\r\n}\r\n```\r\n \r\n## Пример запроса (по текущему паролю):\r\n`POST /Passwords/change`\r\n \r\n```json\r\n{\r\n \"password\": \"MyNewP%40ssw0rd\",\r\n \"currentPassword\": \"OldP%40ssw0rd\"\r\n}\r\n```\r\n \r\n## Пример запроса (по хэшу из e-mail):\r\n`POST /Passwords/change`\r\n \r\n```json\r\n{\r\n \"password\": \"MyNewP%40ssw0rd\",\r\n \"codeHash\": \"a1b2c3d4e5f6\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202):\r\nТело ответа пустое.\r\n \r\n## Негативные сценарии:\r\n- 403 Forbidden: указан `currentPassword`, но пользователь не аутентифицирован.\r\n- 409 Conflict: неверный текущий пароль или некорректный верификационный код.",
990
1038
  "parameters": [
991
1039
  {
992
1040
  "name": "X-Application-ID",
@@ -1059,7 +1107,7 @@
1059
1107
  "VerificationCodes"
1060
1108
  ],
1061
1109
  "summary": "Проверяет верификационный код.",
1062
- "description": "Заголовок `Authorization` **не обязателен**. Для проверки по SMS достаточно тела запроса с `code` и `mobilePhone`.\r\n \r\n## Пример запроса (по хэшу из e-mail):\r\n```json\r\nPOST /VerificationCodes/check\r\n \r\n{\r\n \"codeHash\": \"a1b2c3d4e5f6\"\r\n}\r\n```\r\n \r\n## Пример запроса (по SMS-коду):\r\n```json\r\nPOST /VerificationCodes/check\r\n \r\n{\r\n \"code\": \"123456\",\r\n \"mobilePhone\": \"+79001234567\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"accountID\": 1001,\r\n \"oneTimeLoginToken\": \"olt-abc123xyz\",\r\n \"verificationCodeRepeatTimeout\": 60\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 409 Conflict: тело запроса не указано, ошибки валидации, верификационный код не найден или недействителен.",
1110
+ "description": "Заголовок `Authorization` **не обязателен**. Для проверки по SMS достаточно тела запроса с `code` и `mobilePhone`.\r\n \r\n## Пример запроса (по хэшу из e-mail):\r\n`POST /VerificationCodes/check`\r\n \r\n```json\r\n{\r\n \"codeHash\": \"a1b2c3d4e5f6\"\r\n}\r\n```\r\n \r\n## Пример запроса (по SMS-коду):\r\n`POST /VerificationCodes/check`\r\n \r\n```json\r\n{\r\n \"code\": \"123456\",\r\n \"mobilePhone\": \"+79001234567\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"accountID\": 1001,\r\n \"oneTimeLoginToken\": \"olt-abc123xyz\",\r\n \"verificationCodeRepeatTimeout\": 60\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 409 Conflict: тело запроса не указано, ошибки валидации, верификационный код не найден или недействителен.",
1063
1111
  "parameters": [
1064
1112
  {
1065
1113
  "name": "X-Application-ID",
@@ -1308,7 +1356,7 @@
1308
1356
  "properties": {
1309
1357
  "codeHash": {
1310
1358
  "type": "string",
1311
- "description": "Хэш верификационного кода. Отправляется по элетронной почте. Если поле заполнено, все остольные поля будут проигнорированы.",
1359
+ "description": "Хэш верификационного кода. Отправляется по электронной почте. Если поле заполнено, все остальные поля будут проигнорированы.",
1312
1360
  "nullable": true,
1313
1361
  "example": "a1b2c3d4e5f6"
1314
1362
  },
@@ -1320,7 +1368,7 @@
1320
1368
  },
1321
1369
  "mobilePhone": {
1322
1370
  "type": "string",
1323
- "description": "Номер мобильного телефона, на котрый был отправлен код подтверждения.",
1371
+ "description": "Номер мобильного телефона, на который был отправлен код подтверждения.",
1324
1372
  "nullable": true,
1325
1373
  "example": "+79001234567"
1326
1374
  },
@@ -1477,7 +1525,7 @@
1477
1525
  "properties": {
1478
1526
  "notificationID": {
1479
1527
  "type": "integer",
1480
- "description": "дентификатор уведомления",
1528
+ "description": "Идентификатор уведомления",
1481
1529
  "format": "int32",
1482
1530
  "example": 501
1483
1531
  },
@@ -1525,7 +1573,7 @@
1525
1573
  "properties": {
1526
1574
  "codeHash": {
1527
1575
  "type": "string",
1528
- "description": "Хэш верификационного кода. Отправляется по элетронной почте. Если поле заполнено, все остольные поля будут проигнорированы.",
1576
+ "description": "Хэш верификационного кода. Отправляется по электронной почте. Если поле заполнено, все остальные поля будут проигнорированы.",
1529
1577
  "nullable": true,
1530
1578
  "example": "a1b2c3d4e5f6"
1531
1579
  },
@@ -1537,7 +1585,7 @@
1537
1585
  },
1538
1586
  "mobilePhone": {
1539
1587
  "type": "string",
1540
- "description": "Номер мобильного телефона, на котрый был отправлен код подтверждения.",
1588
+ "description": "Номер мобильного телефона, на который был отправлен код подтверждения.",
1541
1589
  "nullable": true,
1542
1590
  "example": "+79001234567"
1543
1591
  },
@@ -1561,7 +1609,7 @@
1561
1609
  }
1562
1610
  },
1563
1611
  "additionalProperties": false,
1564
- "description": "Данные дял смены пароля"
1612
+ "description": "Данные для смены пароля"
1565
1613
  },
1566
1614
  "RequestPasswordChangeData": {
1567
1615
  "required": [
@@ -1657,7 +1705,7 @@
1657
1705
  "properties": {
1658
1706
  "accountID": {
1659
1707
  "type": "integer",
1660
- "description": "Идентификатор уч.записи, которя запросила провекру почты (указывается только для неаутентифицированного пользователя)",
1708
+ "description": "Идентификатор уч.записи, которая запросила проверку почты (указывается только для неаутентифицированного пользователя)",
1661
1709
  "format": "int32",
1662
1710
  "nullable": true,
1663
1711
  "example": 1001
@@ -1677,7 +1725,7 @@
1677
1725
  "properties": {
1678
1726
  "accountID": {
1679
1727
  "type": "integer",
1680
- "description": "Идентификатор уч.записи, которя запросила провекру телефона (указывается только для неаутентифицированного пользователя)",
1728
+ "description": "Идентификатор уч.записи, которая запросила проверку телефона (указывается только для неаутентифицированного пользователя)",
1681
1729
  "format": "int32",
1682
1730
  "nullable": true,
1683
1731
  "example": 1001
@@ -1717,7 +1765,7 @@
1717
1765
  },
1718
1766
  {
1719
1767
  "name": "VerificationCodes",
1720
- "description": "Контроллер управления прговерочными кодами"
1768
+ "description": "Контроллер управления проверочными кодами"
1721
1769
  },
1722
1770
  {
1723
1771
  "name": "Accounts",
@@ -1733,7 +1781,7 @@
1733
1781
  },
1734
1782
  {
1735
1783
  "name": "VerificationCodes",
1736
- "description": "Контроллер управления прговерочными кодами"
1784
+ "description": "Контроллер управления проверочными кодами"
1737
1785
  }
1738
1786
  ]
1739
1787
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "openapi": "3.0.1",
3
3
  "info": {
4
- "title": "Authenticatin and authorization API for HubEx",
4
+ "title": "Authentication and authorization API for HubEx",
5
5
  "description": "Performs all of the operations, necessary to authenticate and authorize a user as a valid tenant member. Offers an API for registering, verifying e-mail, changing password, etc.",
6
6
  "contact": {
7
7
  "name": "SmartService Backend Team",
@@ -192,7 +192,7 @@
192
192
  "Accounts"
193
193
  ],
194
194
  "summary": "Отправляет SMS с кодом для входа.",
195
- "description": "## Пример запроса:\r\n```json\r\nPOST /Accounts/smsSend\r\n \r\n{\r\n \"phone\": \"+79001234567\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\nТело ответа пустое.\r\n \r\n## Негативные сценарии:\r\n- 400 Bad Request — некорректное тело запроса.\r\n- 401 Unauthorized — регистрация аккаунта не завершена.\r\n- 404 Not Found — аккаунт с указанным телефоном не найден.\r\n- 403 Forbidden — аккаунт заблокирован.\r\n- 429 Too Many Requests — превышен лимит отправки SMS (заголовок `X-SmsBanTill`).",
195
+ "description": "## Пример запроса:\r\n```json\r\n{\r\n \"phone\": \"+79001234567\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\nТело ответа пустое.\r\n \r\n## Негативные сценарии:\r\n- 400 Bad Request — некорректное тело запроса.\r\n- 401 Unauthorized — регистрация аккаунта не завершена.\r\n- 404 Not Found — аккаунт с указанным телефоном не найден.\r\n- 403 Forbidden — аккаунт заблокирован.\r\n- 429 Too Many Requests — превышен лимит отправки SMS (заголовок `X-SmsBanTill`).",
196
196
  "parameters": [
197
197
  {
198
198
  "name": "X-Application-ID",
@@ -378,7 +378,7 @@
378
378
  "Accounts"
379
379
  ],
380
380
  "summary": "Проверяет SMS-код и выполняет вход.",
381
- "description": "## Пример запроса:\r\n```json\r\nPOST /Accounts/smsLogin\r\n \r\n{\r\n \"phone\": \"+79001234567\",\r\n \"code\": \"123456\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\nФормат ответа совпадает с `POST /Accounts/login`.\r\n \r\n## Негативные сценарии:\r\n- 400 Bad Request — некорректное тело запроса.\r\n- 401 Unauthorized — неверный SMS-код, код не был запрошен, истёкло время проверки или регистрация аккаунта не завершена.\r\n- 404 Not Found — аккаунт не найден.\r\n- 403 Forbidden — аккаунт заблокирован.",
381
+ "description": "## Пример запроса:\r\n```json\r\n{\r\n \"phone\": \"+79001234567\",\r\n \"code\": \"123456\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\nФормат ответа совпадает с `POST /Accounts/login`.\r\n \r\n## Негативные сценарии:\r\n- 400 Bad Request — некорректное тело запроса.\r\n- 401 Unauthorized — неверный SMS-код, код не был запрошен, истёкло время проверки или регистрация аккаунта не завершена.\r\n- 404 Not Found — аккаунт не найден.\r\n- 403 Forbidden — аккаунт заблокирован.",
382
382
  "parameters": [
383
383
  {
384
384
  "name": "X-Application-ID",
@@ -552,7 +552,7 @@
552
552
  "Accounts"
553
553
  ],
554
554
  "summary": "Возвращает реалмы SSO для аккаунта по e-mail или домену.",
555
- "description": "Поддерживает ограничение результата через заголовок `Range`.\r\n \r\n## Пример запроса:\r\n```json\r\nPOST /Accounts/realm\r\nRange: items=1-50\r\n \r\n{\r\n \"credential\": \"user@company.com\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n[\r\n {\r\n \"tenantID\": 10,\r\n \"tenantName\": \"Demo Tenant\",\r\n \"realm\": \"demo\"\r\n }\r\n]\r\n```\r\n \r\n## Пример успешного ответа (206):\r\nТело ответа имеет тот же формат, что и для `200`, но содержит только часть диапазона. Заголовок `Content-Range` указывает общее количество.\r\n \r\n## Негативные сценарии:\r\n- 400 Bad Request — не указан credential.\r\n- 204 No Content — реалмы для указанного credential не найдены.",
555
+ "description": "Поддерживает ограничение результата через заголовок `Range` (например, `Range: items=1-50`).\r\n \r\n## Пример запроса:\r\n```json\r\n{\r\n \"credential\": \"user@company.com\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n[\r\n {\r\n \"tenantID\": 10,\r\n \"tenantName\": \"Demo Tenant\",\r\n \"realm\": \"demo\"\r\n }\r\n]\r\n```\r\n \r\n## Пример успешного ответа (206):\r\nТело ответа имеет тот же формат, что и для `200`, но содержит только часть диапазона. Заголовок `Content-Range` указывает общее количество.\r\n \r\n## Негативные сценарии:\r\n- 400 Bad Request — не указан credential.\r\n- 204 No Content — реалмы для указанного credential не найдены.",
556
556
  "parameters": [
557
557
  {
558
558
  "name": "Range",
@@ -730,7 +730,7 @@
730
730
  "Passwords"
731
731
  ],
732
732
  "summary": "Устанавливает пароль для учётной записи.",
733
- "description": "## Пример запроса (по SMS-коду):\r\n```json\r\nPOST /Passwords/set\r\n \r\n{\r\n \"password\": \"MyNewP%40ssw0rd\",\r\n \"code\": \"123456\",\r\n \"mobilePhone\": \"+79001234567\"\r\n}\r\n```\r\n \r\n## Пример запроса (по хэшу из e-mail):\r\n```json\r\nPOST /Passwords/set\r\n \r\n{\r\n \"password\": \"MyNewP%40ssw0rd\",\r\n \"codeHash\": \"a1b2c3d4e5f6\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202):\r\n```json\r\n{\r\n \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"refresh_token\": null,\r\n \"expires_in\": 3600,\r\n \"jwtValidTill\": \"2024-06-15T10:00:00Z\",\r\n \"accountUserTypeID\": 1\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 400 Bad Request — не указаны обязательные поля или некорректное тело запроса.\r\n- 401 Unauthorized — аккаунт по коду верификации не найден.",
733
+ "description": "## Пример запроса (по SMS-коду):\r\n```json\r\n{\r\n \"password\": \"MyNewP%40ssw0rd\",\r\n \"code\": \"123456\",\r\n \"mobilePhone\": \"+79001234567\"\r\n}\r\n```\r\n \r\n## Пример запроса (по хэшу из e-mail):\r\n```json\r\n{\r\n \"password\": \"MyNewP%40ssw0rd\",\r\n \"codeHash\": \"a1b2c3d4e5f6\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (202):\r\n```json\r\n{\r\n \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"refresh_token\": null,\r\n \"expires_in\": 3600,\r\n \"jwtValidTill\": \"2024-06-15T10:00:00Z\",\r\n \"accountUserTypeID\": 1\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 400 Bad Request — не указаны обязательные поля или некорректное тело запроса.\r\n- 401 Unauthorized — аккаунт по коду верификации не найден.",
734
734
  "parameters": [
735
735
  {
736
736
  "name": "X-Application-ID",
@@ -21,7 +21,7 @@
21
21
  "AccessTokens"
22
22
  ],
23
23
  "summary": "Обновляет access-токен по refresh-токену, одноразовому токену или сервисному токену.",
24
- "description": "Поддерживает три способа аутентификации (достаточно одного):\r\n- `refreshJwt` — JWT refresh-токен;\r\n- `oneTimeLoginToken` + `tenantID` — одноразовый токен входа;\r\n- `serviceToken` — сервисный токен.\r\n \r\nПри заголовке `X-Use-Cookie: true` refresh-токен читается из cookie `RefreshTokenCookie`; в теле достаточно пустого JSON-объекта `{}` (поле `refreshJwt` необязательно). Отсутствие тела запроса не поддерживается.\r\n \r\nОпциональный заголовок `X-Application-ID` проверяет доступ к указанному приложению.\r\n \r\n## Пример запроса (refresh-токен):\r\n```json\r\nPOST /AccessTokens\r\n \r\n{\r\n \"refreshJwt\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"accessJwt\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"\r\n}\r\n```\r\n \r\n## Пример запроса (X-Use-Cookie):\r\n```json\r\nPOST /AccessTokens\r\nX-Use-Cookie: true\r\n \r\n{}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"expires_in\": 3600,\r\n \"jwtValidTill\": \"2024-06-15T10:00:00Z\",\r\n \"profile\": { \"userID\": 42, \"firstName\": \"Иван\", \"lastName\": \"Иванов\" },\r\n \"permissions\": {},\r\n \"tenant\": { \"id\": 10, \"name\": \"Demo\", \"fullName\": \"Demo Tenant LLC\", \"uriName\": \"demo\" },\r\n \"tenantMember\": { \"id\": 1001, \"userID\": 42, \"accountID\": 100 }\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — не удалось определить члена тенанта по переданным данным.\r\n- 400 Bad Request — отсутствует тело при работе без cookie, некорректный или просроченный токен.\r\n- 403 Forbidden — нет доступа к указанному приложению (заголовок `X-Application-ID`).",
24
+ "description": "Поддерживает три способа аутентификации (достаточно одного):\r\n- `refreshJwt` — JWT refresh-токен;\r\n- `oneTimeLoginToken` + `tenantID` — одноразовый токен входа;\r\n- `serviceToken` — сервисный токен.\r\n \r\nПри заголовке `X-Use-Cookie: true` refresh-токен читается из cookie `RefreshTokenCookie`; в теле достаточно пустого JSON-объекта `{}` (поле `refreshJwt` необязательно). Отсутствие тела запроса не поддерживается.\r\n \r\nОпциональный заголовок `X-Application-ID` проверяет доступ к указанному приложению.\r\n \r\n## Пример запроса (refresh-токен):\r\n```json\r\n{\r\n \"refreshJwt\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"accessJwt\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"\r\n}\r\n```\r\n \r\n## Пример запроса (X-Use-Cookie):\r\n```json\r\n{}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"expires_in\": 3600,\r\n \"jwtValidTill\": \"2024-06-15T10:00:00Z\",\r\n \"profile\": { \"userID\": 42, \"firstName\": \"Иван\", \"lastName\": \"Иванов\" },\r\n \"permissions\": {},\r\n \"tenant\": { \"id\": 10, \"name\": \"Demo\", \"fullName\": \"Demo Tenant LLC\", \"uriName\": \"demo\" },\r\n \"tenantMember\": { \"id\": 1001, \"userID\": 42, \"accountID\": 100 }\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — не удалось определить члена тенанта по переданным данным.\r\n- 400 Bad Request — отсутствует тело при работе без cookie, некорректный или просроченный токен.\r\n- 403 Forbidden — нет доступа к указанному приложению (заголовок `X-Application-ID`).",
25
25
  "parameters": [
26
26
  {
27
27
  "name": "X-Application-ID",
@@ -166,7 +166,7 @@
166
166
  "Accounts"
167
167
  ],
168
168
  "summary": "Авторизует учётную запись в указанном тенанте.",
169
- "description": "Тело запроса целиком можно опустить — тогда `tenantID` и `tenantMemberID` берутся из JWT текущего пользователя.\r\nЕсли тело передано, оба поля (`tenantID`, `tenantMemberID`) обязательны и должны быть больше 0.\r\n \r\n## Пример запроса:\r\n```json\r\nPOST /Accounts/authorize\r\nAuthorization: Bearer <access-token>\r\n \r\n{\r\n \"tenantID\": 10,\r\n \"tenantMemberID\": 1001\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"expires_in\": 3600,\r\n \"jwtValidTill\": \"2024-06-15T10:00:00Z\",\r\n \"profile\": {\r\n \"userID\": 42,\r\n \"firstName\": \"Иван\",\r\n \"lastName\": \"Иванов\"\r\n },\r\n \"permissions\": { \"TaskView\": \"Allow\" },\r\n \"tenantLicenses\": [],\r\n \"featureFlags\": [],\r\n \"roleTaskAttribute\": []\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 400 Bad Request — передано неполное или некорректное тело (например `{}` или только одно из полей).",
169
+ "description": "Тело запроса целиком можно опустить — тогда `tenantID` и `tenantMemberID` берутся из JWT текущего пользователя.\r\nЕсли тело передано, оба поля (`tenantID`, `tenantMemberID`) обязательны и должны быть больше 0.\r\n \r\n## Пример запроса:\r\n```json\r\n{\r\n \"tenantID\": 10,\r\n \"tenantMemberID\": 1001\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"expires_in\": 3600,\r\n \"jwtValidTill\": \"2024-06-15T10:00:00Z\",\r\n \"profile\": {\r\n \"userID\": 42,\r\n \"firstName\": \"Иван\",\r\n \"lastName\": \"Иванов\"\r\n },\r\n \"permissions\": { \"TaskView\": \"Allow\" },\r\n \"tenantLicenses\": [],\r\n \"featureFlags\": [],\r\n \"roleTaskAttribute\": []\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 403 Forbidden — JWT не содержит признака аутентифицированной учётной записи (`Authenticated`).\r\n- 400 Bad Request — передано неполное или некорректное тело (например `{}` или только одно из полей).",
170
170
  "parameters": [
171
171
  {
172
172
  "name": "X-Application-ID",
@@ -274,7 +274,7 @@
274
274
  "description": "Токен отсутствует или некорректен."
275
275
  },
276
276
  "403": {
277
- "description": "Forbidden"
277
+ "description": "JWT не содержит признака аутентифицированной учётной записи (`Authenticated`)."
278
278
  }
279
279
  },
280
280
  "security": [
@@ -290,7 +290,7 @@
290
290
  "RefreshTokens"
291
291
  ],
292
292
  "summary": "Генерирует refresh-токен для текущего члена тенанта.",
293
- "description": "При заголовке `X-Use-Cookie: true` refresh-токен записывается в HttpOnly-cookie, тело ответа пустое.\r\n \r\n## Пример запроса:\r\n```json\r\nPOST /RefreshTokens\r\nAuthorization: Bearer <access-token>\r\n \r\n{\r\n \"validity\": \"30.00:00:00\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200/201):\r\n```json\r\n{\r\n \"access_token\": \"\",\r\n \"refresh_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"expires_in\": 2592000,\r\n \"jwtValidTill\": \"2024-07-15T10:00:00Z\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа при X-Use-Cookie (200/201):\r\nТело ответа пустое, refresh-токен в cookie `RefreshTokenCookie`.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 400 Bad Request — некорректные параметры или ошибка настройки CORS при использовании cookie.",
293
+ "description": "При заголовке `X-Use-Cookie: true` refresh-токен записывается в HttpOnly-cookie, тело ответа пустое.\r\n \r\n## Пример запроса:\r\n```json\r\n{\r\n \"validity\": \"30.00:00:00\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200/201):\r\n```json\r\n{\r\n \"access_token\": \"\",\r\n \"refresh_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"expires_in\": 2592000,\r\n \"jwtValidTill\": \"2024-07-15T10:00:00Z\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа при X-Use-Cookie (200/201):\r\nТело ответа пустое, refresh-токен в cookie `RefreshTokenCookie`.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 403 Forbidden — JWT не содержит авторизации в тенанте (`TenantMember`).\r\n- 400 Bad Request — некорректные параметры или ошибка настройки CORS при использовании cookie.",
294
294
  "parameters": [
295
295
  {
296
296
  "name": "X-Application-ID",
@@ -418,7 +418,7 @@
418
418
  "description": "Токен отсутствует или некорректен."
419
419
  },
420
420
  "403": {
421
- "description": "Forbidden"
421
+ "description": "JWT не содержит авторизации в тенанте (`TenantMember`)."
422
422
  }
423
423
  },
424
424
  "security": [
@@ -432,7 +432,7 @@
432
432
  "RefreshTokens"
433
433
  ],
434
434
  "summary": "Возвращает refresh-токен с параметрами по умолчанию.",
435
- "description": "При заголовке `X-Use-Cookie: true` refresh-токен записывается в HttpOnly-cookie, тело ответа пустое.\r\n \r\n## Пример запроса:\r\n```text\r\nGET /RefreshTokens\r\nAuthorization: Bearer <access-token>\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"access_token\": \"\",\r\n \"refresh_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"expires_in\": 2592000,\r\n \"jwtValidTill\": \"2024-07-15T10:00:00Z\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (204):\r\nRefresh-токен не найден.\r\n \r\n## Пример успешного ответа при X-Use-Cookie (200):\r\nТело ответа пустое, refresh-токен в cookie `RefreshTokenCookie`.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 400 Bad Request — ошибка настройки CORS при использовании cookie.",
435
+ "description": "При заголовке `X-Use-Cookie: true` refresh-токен записывается в HttpOnly-cookie, тело ответа пустое.\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"access_token\": \"\",\r\n \"refresh_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"expires_in\": 2592000,\r\n \"jwtValidTill\": \"2024-07-15T10:00:00Z\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (204):\r\nRefresh-токен не найден.\r\n \r\n## Пример успешного ответа при X-Use-Cookie (200):\r\nТело ответа пустое, refresh-токен в cookie `RefreshTokenCookie`.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 403 Forbidden — JWT не содержит авторизации в тенанте (`TenantMember`).\r\n- 400 Bad Request — ошибка настройки CORS при использовании cookie.",
436
436
  "parameters": [
437
437
  {
438
438
  "name": "X-Application-ID",
@@ -518,7 +518,7 @@
518
518
  "description": "Токен отсутствует или некорректен."
519
519
  },
520
520
  "403": {
521
- "description": "Forbidden"
521
+ "description": "JWT не содержит авторизации в тенанте (`TenantMember`)."
522
522
  }
523
523
  },
524
524
  "security": [
@@ -534,7 +534,7 @@
534
534
  "ServiceTokens"
535
535
  ],
536
536
  "summary": "Генерирует сервисные токены для указанных членов тенанта.",
537
- "description": "## Пример запроса:\r\n```json\r\nPOST /ServiceTokens\r\nAuthorization: Bearer <access-token>\r\n \r\n[1001, 1002]\r\n```\r\n \r\n## Пример успешного ответа (201):\r\n```json\r\n[\r\n {\r\n \"token\": \"svc_abc123def456\",\r\n \"created\": \"2024-06-15T09:00:00Z\",\r\n \"validTill\": \"2025-06-15T09:00:00Z\"\r\n }\r\n]\r\n```\r\n \r\n## Пример успешного ответа (204):\r\nТело ответа пустое — новые токены не были созданы.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 403 Forbidden — недостаточно прав (`ServiceTokenAdd`).",
537
+ "description": "## Пример запроса:\r\n```json\r\n[1001, 1002]\r\n```\r\n \r\n## Пример успешного ответа (201):\r\n```json\r\n[\r\n {\r\n \"token\": \"svc_abc123def456\",\r\n \"created\": \"2024-06-15T09:00:00Z\",\r\n \"validTill\": \"2025-06-15T09:00:00Z\"\r\n }\r\n]\r\n```\r\n \r\n## Пример успешного ответа (204):\r\nТело ответа пустое — новые токены не были созданы.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 403 Forbidden — недостаточно прав (`ServiceTokenAdd`).",
538
538
  "parameters": [
539
539
  {
540
540
  "name": "X-Application-ID",
@@ -641,7 +641,7 @@
641
641
  "description": "Токен отсутствует или некорректен."
642
642
  },
643
643
  "403": {
644
- "description": "Недостаточно прав.",
644
+ "description": "Недостаточно прав `ServiceTokenAdd`.",
645
645
  "content": {
646
646
  "text/plain": {
647
647
  "schema": {
@@ -681,7 +681,7 @@
681
681
  "ServiceTokens"
682
682
  ],
683
683
  "summary": "Удаляет сервисные токены указанных членов тенанта.",
684
- "description": "## Пример запроса:\r\n```json\r\nDELETE /ServiceTokens\r\nAuthorization: Bearer <access-token>\r\n \r\n[1001, 1002]\r\n```\r\n \r\n## Пример успешного ответа (202):\r\nТело ответа пустое.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 403 Forbidden — недостаточно прав (`ServiceTokenRemove`).",
684
+ "description": "## Пример запроса:\r\n```json\r\n[1001, 1002]\r\n```\r\n \r\n## Пример успешного ответа (202):\r\nТело ответа пустое.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 403 Forbidden — недостаточно прав (`ServiceTokenRemove`).",
685
685
  "parameters": [
686
686
  {
687
687
  "name": "X-Application-ID",
@@ -759,7 +759,7 @@
759
759
  "description": "Токен отсутствует или некорректен."
760
760
  },
761
761
  "403": {
762
- "description": "Недостаточно прав.",
762
+ "description": "Недостаточно прав `ServiceTokenRemove`.",
763
763
  "content": {
764
764
  "text/plain": {
765
765
  "schema": {
@@ -801,7 +801,7 @@
801
801
  "Tokens"
802
802
  ],
803
803
  "summary": "Продлевает срок действия текущего JWT access-токена.",
804
- "description": "Токен извлекается из сохранённого Bearer-токена текущего запроса.\r\n \r\n## Пример запроса:\r\n```text\r\nPOST /Tokens/renew\r\nAuthorization: Bearer <access-token>\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"expires_in\": 3600,\r\n \"jwtValidTill\": \"2024-06-15T10:00:00Z\"\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 400 Bad Request — access-токен не найден в контексте аутентификации.",
804
+ "description": "Токен извлекается из сохранённого Bearer-токена текущего запроса.\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"expires_in\": 3600,\r\n \"jwtValidTill\": \"2024-06-15T10:00:00Z\"\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 403 Forbidden — JWT не содержит авторизации в тенанте (`TenantMember`).\r\n- 400 Bad Request — access-токен не найден в контексте аутентификации.",
805
805
  "parameters": [
806
806
  {
807
807
  "name": "X-Application-ID",
@@ -884,7 +884,7 @@
884
884
  "description": "Токен отсутствует или некорректен."
885
885
  },
886
886
  "403": {
887
- "description": "Forbidden"
887
+ "description": "JWT не содержит авторизации в тенанте (`TenantMember`)."
888
888
  }
889
889
  },
890
890
  "security": [
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.0.1",
3
3
  "info": {
4
4
  "title": "API for CM in HubEx",
5
- "description": "Service offers application programming interface for ....",
5
+ "description": "Service offers application programming interface for client mobile geolocation and tracking data.",
6
6
  "contact": {
7
7
  "name": "SmartService Backend Team",
8
8
  "email": "fmbackend@melston.ru"
@@ -21,8 +21,26 @@
21
21
  "Clients"
22
22
  ],
23
23
  "summary": "Сохранение данных о местоположении клиента",
24
- "description": "## Пример запроса:\r\n`POST /Clients/locations`\r\n \r\nЗаголовки:\r\n- `X-Application-Id` — уникальный идентификатор клиента (устройства), обязателен.\r\n- `X-Client-Utc-Offset` — смещение часового пояса клиента в минутах от UTC, необязателен (по умолчанию `0`).\r\n \r\n```json\r\n[\r\n {\r\n \"coordinate\": \"55.75:37.62\",\r\n \"clientTimestamp\": \"2026-08-17T08:30:00Z\",\r\n \"altitude\": 150.5,\r\n \"bearing\": 90.0,\r\n \"accuracy\": 10.0,\r\n \"speed\": 5.2\r\n }\r\n]\r\n```\r\n \r\nАльтернативный формат координат через объект `coords`:\r\n```json\r\n[\r\n {\r\n \"coords\": {\r\n \"latitude\": 55.75,\r\n \"longitude\": 37.62,\r\n \"altitude\": 150.5,\r\n \"accuracy\": 10.0,\r\n \"speed\": 5.2,\r\n \"bearing\": 90.0\r\n },\r\n \"timestamp\": \"2026-08-17T08:30:00Z\"\r\n }\r\n]\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"clientId\": \"device-uuid-12345\",\r\n \"clientOffset\": 180\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 404 Not Found: не передан обязательный заголовок `X-Application-Id`.\r\n- 409 Conflict: пустое или отсутствующее тело запроса.\r\n- 409 Conflict: отсутствуют или некорректны координаты (`coordinate` / `coords`).\r\n- 409 Conflict: `clientTimestamp` раньше 2018-10-01.",
24
+ "description": "## Пример запроса:\r\n`POST /Clients/locations`\r\n \r\nЗаголовки:\r\n- `X-CLIENT-IDENTIFIER` — уникальный идентификатор клиента (устройства), обязателен.\r\n- `X-Client-Utc-Offset` — смещение часового пояса клиента в минутах от UTC, необязателен (по умолчанию `0`).\r\n- `X-Application-ID` — идентификатор приложения-источника запроса (enum 1..6), необязателен.\r\n \r\n```json\r\n[\r\n {\r\n \"coordinate\": \"55.75:37.62\",\r\n \"clientTimestamp\": \"2026-08-17T08:30:00Z\",\r\n \"altitude\": 150.5,\r\n \"bearing\": 90.0,\r\n \"accuracy\": 10.0,\r\n \"speed\": 5.2\r\n }\r\n]\r\n```\r\n \r\nАльтернативный формат координат через объект `coords`:\r\n```json\r\n[\r\n {\r\n \"coords\": {\r\n \"latitude\": 55.75,\r\n \"longitude\": 37.62,\r\n \"altitude\": 150.5,\r\n \"accuracy\": 10.0,\r\n \"speed\": 5.2,\r\n \"bearing\": 90.0\r\n },\r\n \"timestamp\": \"2026-08-17T08:30:00Z\"\r\n }\r\n]\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"clientId\": \"device-uuid-12345\",\r\n \"clientOffset\": 180\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 404 Not Found: не передан обязательный заголовок `X-CLIENT-IDENTIFIER`.\r\n- 409 Conflict: пустое или отсутствующее тело запроса.\r\n- 409 Conflict: отсутствуют или некорректны координаты (`coordinate` / `coords`).\r\n- 409 Conflict: `clientTimestamp` раньше 2018-10-01.",
25
25
  "parameters": [
26
+ {
27
+ "name": "X-CLIENT-IDENTIFIER",
28
+ "in": "header",
29
+ "description": "Уникальный идентификатор клиента (устройства)",
30
+ "required": true,
31
+ "schema": {
32
+ "type": "string"
33
+ }
34
+ },
35
+ {
36
+ "name": "X-Client-Utc-Offset",
37
+ "in": "header",
38
+ "description": "Смещение часового пояса клиента в минутах от UTC",
39
+ "schema": {
40
+ "type": "integer",
41
+ "format": "int32"
42
+ }
43
+ },
26
44
  {
27
45
  "name": "X-Application-ID",
28
46
  "in": "header",
@@ -109,10 +127,10 @@
109
127
  }
110
128
  },
111
129
  "404": {
112
- "description": "Не передан обязательный заголовок X-Application-Id."
130
+ "description": "Не передан обязательный заголовок X-CLIENT-IDENTIFIER."
113
131
  },
114
132
  "409": {
115
- "description": "Ошибка валидации входных данных. Тело ошибки: System.Collections.Generic.List`1.",
133
+ "description": "Ошибка валидации входных данных. Тело ошибки: SmartService.Common.ExceptionHandling.Models.ErrorModel[].",
116
134
  "content": {
117
135
  "text/plain": {
118
136
  "schema": {