API

Serhii
От Serhii
15 статьи

Как получить access token

Access token необходим для авторизации последующих API-запросов в LMS Smart Way. После получения токена вы передаёте его в заголовке Authorization с типом Bearer и используете для обращения к доступным endpoint’ам в соответствии со scope, которые вложены в токен. Эта статья показывает, как получить токен, что именно возвращает API в ответе и на что обратить внимание перед интеграцией. Если вы только начинаете настройку интеграции, сначала убедитесь, что у вас есть действительный company_api_key. Предпосылки - У вас должен быть действительный company_api_key вашей компании. - Запрос на получение токена необходимо выполнять на endpoint /api/v1/auth/token. - API key передаётся в заголовке X-API-Key. - Полученный access token используется только для последующих вызовов API и не заменяет собой API key. Запрос curl -X POST 'https://smartway.pro/api/v1/auth/token' \ -H 'X-API-Key: <company_api_key>' Успешный ответ { "access_token": "<short_lived_jwt>", "token_type": "Bearer", "expires_in": 900, "scope": "academy.read academy.write employees.read employees.write tests.read tests.write files.read" } Зафиксированные правила ответа - access_token — короткоживущий JWT для последующих вызовов public API - token_type — всегда Bearer - expires_in — TTL в секундах - scope — список scope-ов, разделённых пробелами, вложенных в токен Что внутри access token - JWT содержит claim companyId для tenant isolation. - JWT также содержит claim hrEmail — email HRADMIN, который создал или ротировал текущий активный API key компании. - Если API key сгенерирует или ротирует другой HRADMIN, то новые токены уже будут содержать другой hrEmail, и именно он будет использоваться для последующих employee write-операций. Как использовать access token в последующих запросах После успешного получения токена передавайте его в заголовке Authorization в формате Bearer <access_token>. Именно этот токен используется для авторизации последующих запросов к public API. Перед выполнением запроса проверяйте, что токен ещё не истёк. Если срок действия завершился, получите новый access token повторным вызовом endpoint’а авторизации.

Обновлено Mar 28, 2026

Правила текущей реализации API LMS

Public API использует схему: company API key -> short-lived Bearer token Правила текущей реализации: - API key принадлежит компании, а не отдельному пользователю. - Для v1 разрешен один активный API key на компанию. - Управляет ключом только пользователь с ролью HRADMIN в cab > Settings > Company. - Полный секрет показывается только один раз — сразу после генерации или ротации. - После ротации предыдущий ключ становится невалидным сразу. - Интегратор получает access token через POST /v1/auth/token и далее использует Authorization: Bearer <token>. - Refresh token для интегратора в v1 не используется: после завершения TTL access token интегратор повторно вызывает POST /v1/auth/token. Base URL и общие правила вызова 1. Base URL Текущий base URL: - https://smartway.pro/api 2. Общие правила - Формат бизнес-ответов: application/json - Формат ошибок: application/problem+json - Версионирование: major-версия в URI (/v1/...) - Для корреляции запросов рекомендуется передавать traceparent

Обновлено Mar 28, 2026

Как получить список сотрудников через API?

GET /v1/employees возвращает страницу сотрудников. Если query-параметры не переданы, API применяет значения по умолчанию: page = 0 и size = 50. Endpoint | Параметр | Значение | | -------------- | ---------------------- | | Method | GET | | Path | /api/v1/employees | | Base URL | https://smartway.pro | | Auth | Bearer token | | Required scope | employees.read | Назначение Endpoint используется для получения постраничного списка сотрудников в рамках компании из Bearer token. Endpoint поддерживает пагинацию, поиск по ФИО и фильтры по департаменту и должности. Предусловия - Клиент должен передать валидный Bearer token. - Token должен содержать company context. - Token должен содержать scope employees.read. - idCompany не передаётся внешним клиентом. BFF берёт companyId только из Bearer token. - Текстовые query-параметры поддерживают UTF-8 и должны передаваться как стандартный URL-encoded query string. Запрос Query parameters | Параметр | Тип | Обязательный | Описание | | ------------ | ------- | ---------------- | ----------------------------------------------------------------------- | | page | int32 | нет | Номер страницы. Значение по умолчанию: 0. | | size | int32 | нет | Размер страницы. Значение по умолчанию: 50. | | q | string | нет | Поиск по ФИО с частичным совпадением. Поиск по email не поддерживается. | | department | string | нет | Фильтр по департаменту. | | jobTitle | string | нет | Фильтр по должности. | curl пример Вызов без параметров curl -X GET 'https://smartway.pro/api/v1/employees' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Вызов с параметрами curl -X GET 'https://smartway.pro/api/v1/employees?page=0&size=20&q=Иван' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Вызов с несколькими UTF-8 параметрами curl -G 'https://smartway.pro/api/v1/employees' \ --data-urlencode 'page=0' \ --data-urlencode 'size=20' \ --data-urlencode 'q=Иван' \ --data-urlencode 'department=Управление' \ --data-urlencode 'jobTitle=Менеджер' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Ответ Успешный ответ: 200 OK. Возвращает EmployeeListResponse. { "data": [ { "employeeId": 4329, "candidateId": 10602, "email": "employee@example.com", "fullName": "Имя Фамилия", "name": "Имя", "surname": "Фамилия", "gender": "Female", "department": "КЛ", "departments": [ "КЛ" ], "jobTitle": "Менеджер", "jobTitles": [ "Менеджер" ], "phone": "+380000000000", "active": true } ], "meta": { "page": 0, "size": 50, "totalElements": 385, "totalPages": 8, "hasNext": true } } Поля ответа EmployeeListResponse | Поле | Тип | Описание | | -------- | ---------- | --------------------------------------- | | data | Employee[] | Список сотрудников на текущей странице. | | meta | object | Метаданные пагинации. | Employee | Поле | Тип | Описание | | ----------- | -------- | ------------------------------------------------------- | | employeeId | int64 | ID сотрудника. | | candidateId | int64 | ID связанного кандидата. | | email | string | Email сотрудника. | | fullName | string | Полное имя, которое сервер формирует из name + surname. | | name | string | Имя. | | surname | string | Фамилия. | | gender | string | Пол. | | department | string | Основной департамент. | | departments | string[] | Набор департаментов. | | jobTitle | string | Основная должность. | | jobTitles | string[] | Набор должностей. | | phone | string | Телефон. | | active | boolean | Признак активности. | Pagination meta | Поле | Тип | Описание | | ------------- | ------- | ------------------------------------------ | | page | int32 | Номер текущей страницы. Нумерация 0-based. | | size | int32 | Размер страницы. | | totalElements | int64 | Общее количество найденных элементов. | | totalPages | int32 | Общее количество страниц. | | hasNext | boolean | Признак наличия следующей страницы. | Бизнес-логика - Все query-параметры необязательные. - Если endpoint вызвать без параметров, API возвращает первую страницу сотрудников: page = 0, size = 50. - Параметр page является 0-based: page = 0 — первая страница, page = 1 — вторая страница. - BFF берёт companyId только из Bearer token. - idCompany не передаётся внешним клиентом. - Поиск q работает по ФИО с частичным совпадением. - Поиск по email не поддерживается. - Параметры q, department и jobTitle поддерживают UTF-8. - Параметры можно комбинировать. Совокупность параметров применяется через логику AND. - Для доступа нужен scope employees.read. Edge cases Edge cases | Сценарий | Поведение API | | ------------------------------------------------------- | ------------------------------------------------------------- | | Query-параметры не переданы | API применяет page = 0 и size = 50. | | page = 0 | Возвращается первая страница. | | page = 1 | Возвращается вторая страница. | | Передан q | API ищет по ФИО с частичным совпадением. | | Передан email в q | Поиск по email не поддерживается. | | Переданы department и jobTitle | Фильтры комбинируются через AND. | | Передано UTF-8 значение, например department=Управление | Значение валидно, если передано как URL-encoded query string. | | Token без company context | API возвращает 403 Forbidden. | Ошибки Error responses | HTTP status | Когда возникает | | ------------------------- | ------------------------------------------------ | | 400 Bad Request | Некорректные query-параметры. | | 401 Unauthorized | Bearer token отсутствует или невалиден. | | 403 Forbidden | Недостаточно прав или token без company context. | | 500 Internal Server Error | Неожиданная ошибка BFF. | | 503 Service Unavailable | Сбой внутренней интеграции BFF -> back2. | Использование - Первый тест интеграции без query-параметров. - Получение следующей страницы через page. - Изменение размера страницы через size. - Поиск сотрудника по ФИО через q. - Фильтрация сотрудников по department или jobTitle. - Комбинирование поиска и фильтров для узкой выборки. Типичные ошибки Typical integration mistakes | Типичная ошибка | Как правильно | | --------------------------------------- | ------------------------------------------------------------- | | Считать, что page = 1 — первая страница | Используйте page = 0 для первой страницы. | | Искать сотрудника по email через q | q поддерживает поиск по ФИО, а не по email. | | Передавать idCompany в query string | Не передавайте idCompany; companyId берётся из Bearer token. | | Не кодировать UTF-8 значения в URL | Передавайте текстовые параметры как URL-encoded query string. | | Использовать token без employees.read | Для endpoint-а нужен scope employees.read. | FAQ Можно ли вызвать endpoint без query-параметров? Да. API применит page = 0 и size = 50. С какой страницы начинается пагинация? С page = 0. Поддерживается ли поиск по email? Нет. Параметр q ищет по ФИО с частичным совпадением. Можно ли комбинировать фильтры? Да. Параметры комбинируются через логику AND. Нужно ли передавать idCompany? Нет. BFF берёт companyId из Bearer token.

Обновлено May 03, 2026

Как получить сотрудника по ID через API?

GET /v1/employees/{employeeId} возвращает одного сотрудника по ID в рамках tenant-контекста из Bearer token. Endpoint | Параметр | Значение | | -------------- | ------------------------------ | | Method | GET | | Path | /api/v1/employees/{employeeId} | | Base URL | https://smartway.pro | | Auth | Bearer token | | Required scope | employees.read | Назначение Endpoint используется для получения детальной информации об одном сотруднике. Поиск выполняется только в рамках tenant-контекста, определённого Bearer token. Предусловия - Клиент должен передать валидный Bearer token. - Token должен содержать company context. - Token должен содержать scope employees.read. - idCompany не передаётся отдельно. - employeeId должен принадлежать сотруднику в рамках текущего tenant-а. Запрос Path parameters | Параметр | Тип | Обязательный | Описание | | ------------ | ------- | ---------------- | -------------- | | employeeId | int64 | да | ID сотрудника. | curl пример Получить сотрудника по ID curl -X GET 'https://smartway.pro/api/v1/employees/3114' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Ответ Успешный ответ: 200 OK. Возвращает Employee. { "employeeId": 4329, "candidateId": 10602, "email": "employee@example.com", "fullName": "Имя Фамилия", "name": "Имя", "surname": "Фамилия", "gender": "Female", "department": "КЛ", "departments": [ "КЛ" ], "jobTitle": "Менеджер", "jobTitles": [ "Менеджер" ], "phone": "+380000000000", "active": true } Поля ответа Employee | Поле | Тип | Описание | | ----------- | -------- | ------------------------------------------------------- | | employeeId | int64 | ID сотрудника. | | candidateId | int64 | ID связанного кандидата. | | email | string | Email сотрудника. | | fullName | string | Полное имя, которое сервер формирует из name + surname. | | name | string | Имя. | | surname | string | Фамилия. | | gender | string | Пол. | | department | string | Основной департамент. | | departments | string[] | Набор департаментов. | | jobTitle | string | Основная должность. | | jobTitles | string[] | Набор должностей. | | phone | string | Телефон. | | active | boolean | Признак активности. | Бизнес-логика - BFF берёт companyId из Bearer token. - idCompany не передаётся отдельным параметром. - Поиск сотрудника выполняется в рамках tenant-контекста из Bearer token. - Если employeeId не найден в текущем tenant-е, API возвращает 404 Not Found. - Для доступа нужен scope employees.read. - fullName является производным полем и формируется сервером из name + surname. Edge cases Edge cases | Сценарий | Поведение API | | ---------------------------------------- | ----------------------------------------------------------- | | employeeId существует в текущем tenant-е | API возвращает 200 OK и Employee. | | employeeId не найден в текущем tenant-е | API возвращает 404 Not Found. | | employeeId существует в другой компании | API не возвращает сотрудника вне текущего tenant-контекста. | | Bearer token без company context | API возвращает 403 Forbidden. | | Клиент передаёт idCompany | Endpoint не использует idCompany из клиентского запроса. | Ошибки Error responses | HTTP status | Когда возникает | | ------------------------- | ------------------------------------------------ | | 400 Bad Request | Некорректный запрос. | | 401 Unauthorized | Bearer token отсутствует или невалиден. | | 403 Forbidden | Недостаточно прав или token без company context. | | 404 Not Found | Сотрудник не найден в рамках текущего tenant-а. | | 500 Internal Server Error | Неожиданная ошибка BFF. | | 503 Service Unavailable | Сбой внутренней интеграции BFF -> back2. | Использование - Получить карточку сотрудника по employeeId. - Проверить результат создания или обновления сотрудника. - Синхронизировать данные одного сотрудника во внешней системе. - Проверить, доступен ли employeeId в рамках текущего tenant-а. Типичные ошибки Typical integration mistakes | Типичная ошибка | Как правильно | | ------------------------------------------- | ----------------------------------------------------------- | | Передавать idCompany вместе с employeeId | Не передавайте idCompany; tenant определяется Bearer token. | | Использовать token без employees.read | Для чтения сотрудника нужен scope employees.read. | | Ожидать доступ к сотруднику другой компании | API ищет только в текущем tenant-контексте. | | Считать 404 технической ошибкой | 404 означает, что сотрудник не найден в текущем tenant-е. | FAQ Нужно ли передавать idCompany? Нет. companyId берётся из Bearer token. Какой scope нужен? employees.read. Что будет, если employeeId не найден? API вернёт 404 Not Found. Возвращается ли fullName? Да. fullName возвращается как поле Employee и формируется сервером из name + surname.

Обновлено May 03, 2026

Как добавить сотрудника через API?

POST /v1/employees создаёт сотрудника. Обязательные поля body: email, name, surname, gender и active. Для доступа нужен scope employees.write. Endpoint | Параметр | Значение | | -------------- | ---------------------- | | Method | POST | | Path | /api/v1/employees | | Base URL | https://smartway.pro | | Auth | Bearer token | | Required scope | employees.write | Назначение Endpoint используется для создания нового сотрудника в рамках компании из Bearer token. Значение active управляет не только бизнес-флагом, но и созданием или отсутствием связанного пользователя в Keycloak. Предусловия - Клиент должен передать валидный Bearer token. - Token должен содержать company context. - Token должен содержать scope employees.write. - idCompany не передаётся в body или query string. - hrEmail не передаётся внешним клиентом; BFF берёт его из Bearer token. - В текущей реализации Idempotency-Key не используется. Запрос Body parameters | Поле | Тип | Обязательное | Описание | | ----------- | -------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | email | string | да | Email сотрудника. | | name | string | да | Имя сотрудника. Это source of truth для формирования fullName при создании. | | surname | string | да | Фамилия сотрудника. Это source of truth для формирования fullName при создании. | | gender | string | да | Допустимы только значения Male или Female. | | active | boolean | да | Допустимы только JSON-boolean значения true или false. true создаёт или синхронизирует доступ к личному кабинету через Keycloak; false создаёт сотрудника без такого доступа. | | department | string | нет | Основной департамент. Если не передать, сохраняется null. | | departments | string[] | нет | Набор департаментов. Если не передать, коллекция остаётся пустой. | | jobTitle | string | нет | Основная должность. Если не передать, сохраняется null. | | jobTitles | string[] | нет | Набор должностей. Если не передать, коллекция остаётся пустой. | | phone | string | нет | Телефон. Если не передать, сохраняется null. | | notes | string | нет | Примечания. Если не передать, сохраняется null. | curl пример Создать сотрудника с primary-полями и массивами curl -X POST 'https://smartway.pro/api/v1/employees' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ --data-binary @- <<'JSON' { "email": "employee@example.com", "name": "Иван", "surname": "Петренко", "gender": "Female", "active": false, "department": "Управление", "departments": ["КЛ"], "jobTitle": "Менеджер", "jobTitles": ["Координатор"], "phone": "+380000000000", "notes": "Новый сотрудник public API" } JSON Создать сотрудника только с массивами departments/jobTitles curl -X POST 'https://smartway.pro/api/v1/employees' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ --data-binary @- <<'JSON' { "email": "employee@example.com", "name": "Иван", "surname": "Петренко", "gender": "Male", "active": true, "departments": ["Управление", "КЛ"], "jobTitles": ["Менеджер", "Координатор"], "phone": "+380000000000", "notes": "Новый сотрудник public API" } JSON Ответ Успешный ответ: 201 Created. Возвращает созданный Employee. { "employeeId": 4432, "candidateId": 10748, "email": "employee@example.com", "fullName": "Иван Петренко", "name": "Иван", "surname": "Петренко", "gender": "Female", "department": "Управление", "departments": [ "КЛ", "Управление" ], "jobTitle": "Менеджер", "jobTitles": [ "Координатор", "Менеджер" ], "phone": "+380000000000", "active": false } Поля ответа Employee | Поле | Тип | Описание | | ----------- | -------- | ------------------------------------------------------- | | employeeId | int64 | ID сотрудника. | | candidateId | int64 | ID связанного кандидата. | | email | string | Email сотрудника. | | fullName | string | Полное имя, которое сервер формирует из name + surname. | | name | string | Имя. | | surname | string | Фамилия. | | gender | string | Пол. | | department | string | Основной департамент. | | departments | string[] | Набор департаментов. | | jobTitle | string | Основная должность. | | jobTitles | string[] | Набор должностей. | | phone | string | Телефон. | | active | boolean | Признак активности. | Бизнес-логика - BFF определяет companyId только из Bearer token. - BFF берёт hrEmail из Bearer token. hrEmail равен email пользователя с ролью HRADMIN, который создал или ротировал активный API key компании. - Если активный API key будет ротирован другим HRADMIN, следующие create-операции автоматически начнут использовать его hrEmail. - Повторный одинаковый POST не создаёт дубль, если уже существует employee с таким же email; API возвращает 409 Conflict. - gender принимает только Male или Female. - active принимает только JSON-boolean true или false. - active = true создаёт или синхронизирует связанный пользовательский аккаунт в Keycloak и открывает доступ к личному кабинету. - active = false создаёт сотрудника без доступа к личному кабинету, то есть без пользователя в Keycloak. - fullName в ответе формируется сервером из name + surname. - Если передан только departments или jobTitles, первый элемент массива становится primary-значением в department или jobTitle. - Если передано и одиночное поле, и массив, одиночное поле имеет приоритет как primary, а массив дополняется уникальными значениями. - Если department, jobTitle, phone или notes не переданы, в соответствующих одиночных полях сохраняется null. - Если departments или jobTitles не переданы, соответствующие коллекции остаются пустыми. - В ответе departments и jobTitles возвращаются в стабильно отсортированном виде. Edge cases Edge cases | Сценарий | Поведение API | | ----------------------------------------- | --------------------------------------------------------------------------------------- | | Отсутствует required-поле | API возвращает 400 Bad Request. | | gender имеет значение не Male и не Female | API возвращает 400 Bad Request с пояснением. | | active передан строкой или числом | API возвращает 400 Bad Request, потому что active должен быть JSON-boolean. | | email уже существует | API возвращает 409 Conflict. | | Передан только departments | Первый элемент массива становится department. | | Переданы department и departments | department остаётся primary, а departments дополняется уникальными значениями. | | Не передан department или jobTitle | В соответствующем одиночном поле сохраняется null. | | Не передан departments или jobTitles | Соответствующая коллекция остаётся пустой. | | Клиент передаёт fullName | В create request поле fullName не описано. Сервер формирует fullName из name + surname. | Ошибки Error responses | HTTP status | Когда возникает | | ------------------------- | ----------------------------------------------------------------------------------- | | 400 Bad Request | Отсутствует хотя бы один required-параметр email, name, surname, gender или active. | | 400 Bad Request | gender не равен Male или Female. | | 400 Bad Request | active не является JSON-boolean значением true или false. | | 401 Unauthorized | Bearer token отсутствует или невалиден. | | 403 Forbidden | Недостаточно прав или token без company context. | | 409 Conflict | Employee с таким email уже существует. | | 500 Internal Server Error | Неожиданная ошибка BFF. | | 503 Service Unavailable | Сбой внутренней интеграции BFF -> back2. | Использование - Создать активного сотрудника с доступом к личному кабинету: active = true. - Создать сотрудника без доступа к личному кабинету: active = false. - Передать несколько департаментов или должностей с определением primary-значения. - Синхронизировать сотрудников из внешней HR-системы. Типичные ошибки Typical integration mistakes | Типичная ошибка | Как правильно | | ----------------------------------------------------- | ---------------------------------------------------------- | | Передавать active как строку "true" или "false" | Передавайте true или false как JSON-boolean. | | Передавать gender в значении, отличном от Male/Female | Используйте только Male или Female. | | Передавать idCompany или hrEmail | Не передавайте эти значения; BFF берёт их из Bearer token. | | Ожидать идемпотентность через Idempotency-Key | В текущей реализации Idempotency-Key не используется. | | Передавать fullName вместо name и surname | Передавайте name и surname; fullName формирует сервер. | FAQ Какие поля обязательны для создания сотрудника? email, name, surname, gender и active. Что делает active = true? Сервер создаёт или синхронизирует связанный пользовательский аккаунт в Keycloak и открывает доступ к личному кабинету. Что делает active = false? Сотрудник создаётся без доступа к личному кабинету, то есть без пользователя в Keycloak. Что будет, если email уже существует? API вернёт 409 Conflict. Нужно ли передавать hrEmail? Нет. BFF берёт hrEmail из Bearer token.

Обновлено May 03, 2026

Как частично обновить данные сотрудника через API?

PATCH /v1/employees/{employeeId} обновляет только переданные поля. Body должен содержать хотя бы одно поле. Для доступа нужен scope employees.write. Endpoint | Параметр | Значение | | -------------- | ------------------------------ | | Method | PATCH | | Path | /api/v1/employees/{employeeId} | | Base URL | https://smartway.pro | | Auth | Bearer token | | Required scope | employees.write | Назначение Endpoint используется для частичного обновления сотрудника в рамках текущего tenant-а. Поле fullName не входит в PATCH-контракт; для изменения ФИО используются name и surname. Предусловия - Клиент должен передать валидный Bearer token. - Token должен содержать company context. - Token должен содержать scope employees.write. - employeeId должен принадлежать сотруднику в рамках текущего tenant-а. - PATCH-body должен содержать хотя бы одно поле. - idCompany и hrEmail не передаются внешним клиентом. Запрос Path parameters | Параметр | Тип | Обязательный | Описание | | ------------ | ------- | ---------------- | -------------- | | employeeId | int64 | да | ID сотрудника. | Body parameters | Поле | Тип | Обязательное | Описание | | ----------- | -------- | ---------------- | ------------------------------------------------------------------------------------- | | email | string | нет | Обновить email. | | name | string | нет | Обновить имя сотрудника. Если поле передано, оно должно содержать непустой текст. | | surname | string | нет | Обновить фамилию сотрудника. Если поле передано, оно должно содержать непустой текст. | | gender | string | нет | Обновить пол. | | department | string | нет | Обновить primary-департамент. | | departments | string[] | нет | Заменить полный набор департаментов. | | jobTitle | string | нет | Обновить primary-должность. | | jobTitles | string[] | нет | Заменить полный набор должностей. | | phone | string | нет | Обновить телефон. | | active | boolean | нет | Обновить признак активности. | curl пример Обновить ФИО, primary-поля, массивы и active curl -X PATCH 'https://smartway.pro/api/v1/employees/4432' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ --data-binary @- <<'JSON' { "name": "Обновленное имя", "surname": "Фамилия", "department": "Управление", "departments": ["КЛ", "Логистика"], "jobTitle": "Старший менеджер", "jobTitles": ["Координатор", "Аналитик"], "active": false } JSON Ответ Успешный ответ: 200 OK. Возвращает обновлённый Employee. { "employeeId": 4432, "candidateId": 10748, "email": "employee@example.com", "fullName": "Обновленное имя Фамилия", "name": "Обновленное имя", "surname": "Фамилия", "gender": "not_specified", "department": "Управление", "departments": [ "КЛ", "Логистика", "Управление" ], "jobTitle": "Старший менеджер", "jobTitles": [ "Аналитик", "Координатор", "Старший менеджер" ], "phone": "+380000000000", "active": false } Поля ответа Employee | Поле | Тип | Описание | | ----------- | -------- | ------------------------------------------------------- | | employeeId | int64 | ID сотрудника. | | candidateId | int64 | ID связанного кандидата. | | email | string | Email сотрудника. | | fullName | string | Полное имя, которое сервер формирует из name + surname. | | name | string | Имя. | | surname | string | Фамилия. | | gender | string | Пол. | | department | string | Основной департамент. | | departments | string[] | Набор департаментов. | | jobTitle | string | Основная должность. | | jobTitles | string[] | Набор должностей. | | phone | string | Телефон. | | active | boolean | Признак активности. | Бизнес-логика - BFF берёт companyId из Bearer token, а не из параметров запроса. - BFF берёт hrEmail из Bearer token. hrEmail равен email пользователя с ролью HRADMIN, который создал или ротировал активный API key компании. - Если активный API key будет ротирован другим HRADMIN, следующие patch-операции автоматически начнут использовать его hrEmail. - PATCH изменяет только те поля, которые переданы в body. - fullName не передаётся в PATCH-body. Сервер формирует fullName из актуальных name + surname. - name и surname можно передавать вместе или отдельно. Если поле передано, оно должно содержать непустой текст. - Текстовые поля поддерживают UTF-8. - Если передан только departments или jobTitles, первый элемент массива становится primary-значением. - Если передано и одиночное поле, и массив, одиночное поле остаётся primary. - Массивы departments и jobTitles в ответе возвращаются в отсортированном виде. - Если новый email уже принадлежит другому employee, API возвращает 409 Conflict. - Если active меняется с false на true, сервер создаёт или повторно синхронизирует связанного Keycloak-пользователя и открывает доступ к личному кабинету. - Если active меняется с true на false, сервер удаляет связанного Keycloak-пользователя и отзывает доступ к личному кабинету. - Если PATCH одновременно меняет active и email, сервер синхронизирует именно аккаунт, который уже был связан с этим employee, а не произвольного пользователя по новому email. Edge cases Edge cases | Сценарий | Поведение API | | -------------------------------------------- | ------------------------------------------------------------------------------ | | PATCH-body пустой | API возвращает 400 Bad Request. | | name или surname переданы пустыми | API возвращает 400 Bad Request. | | fullName передан в PATCH-body | Поле не входит в PATCH-контракт; используйте name и surname. | | Новый email уже принадлежит другому employee | API возвращает 409 Conflict. | | Передан только departments или jobTitles | Первый элемент массива становится primary-значением. | | Передано одиночное поле и массив | Одиночное поле остаётся primary, массив в ответе возвращается отсортированным. | | active меняется с false на true | Сервер создаёт или синхронизирует связанного Keycloak-пользователя. | | active меняется с true на false | Сервер удаляет связанного Keycloak-пользователя. | | active и email меняются одновременно | Синхронизируется аккаунт, уже связанный с этим employee. | Ошибки Error responses | HTTP status | Когда возникает | | ------------------------- | ------------------------------------------------------------------------------------------------------------------- | | 400 Bad Request | Пустой PATCH-body или невалидные значения, включая пустые name / surname. | | 401 Unauthorized | Bearer token отсутствует или невалиден. | | 403 Forbidden | Недостаточно прав или token без company context. | | 404 Not Found | Сотрудник не найден в рамках текущего tenant-а. | | 409 Conflict | Новый email уже занят другим employee или не может быть безопасно использован для синхронизации доступа в Keycloak. | | 500 Internal Server Error | Неожиданная ошибка BFF. | | 503 Service Unavailable | Сбой внутренней интеграции BFF -> back2. | Использование - Обновить контактные данные сотрудника. - Изменить департамент или должность. - Включить доступ к личному кабинету через active = true. - Отозвать доступ к личному кабинету через active = false. - Обновить email с проверкой конфликта. Типичные ошибки Typical integration mistakes | Типичная ошибка | Как правильно | | ----------------------------------------------------- | ----------------------------------------------------------------------- | | Отправлять пустой PATCH-body | Передайте хотя бы одно поле для изменения. | | Передавать fullName | Передавайте name и surname. | | Передавать пустые name или surname | Если поле передано, оно должно содержать непустой текст. | | Ожидать, что изменение active только меняет флаг в БД | active также управляет синхронизацией связанного Keycloak-пользователя. | | Передавать idCompany или hrEmail | Не передавайте эти значения; BFF берёт их из Bearer token. | FAQ Можно ли передать только одно поле в PATCH? Да. Body должен содержать хотя бы одно поле. Можно ли изменить fullName напрямую? Нет. fullName не входит в PATCH-контракт. Используйте name и surname. Что будет, если новый email уже занят? API вернёт 409 Conflict. Что происходит при active = false? Сервер удаляет связанного Keycloak-пользователя и отзывает доступ к личному кабинету. Что происходит, если одновременно изменить active и email? Сервер синхронизирует аккаунт, который уже связан с этим employee.

Обновлено May 03, 2026

Как удалить сотрудника через API?

DELETE /v1/employees/{employeeId} удаляет сотрудника в рамках tenant-контекста. Успешный ответ — 204 No Content. Endpoint | Параметр | Значение | | -------------- | ------------------------------ | | Method | DELETE | | Path | /api/v1/employees/{employeeId} | | Base URL | https://smartway.pro | | Auth | Bearer token | | Required scope | employees.write | Назначение Endpoint используется для удаления сотрудника по employeeId. Операция выполняется в рамках tenant-контекста из Bearer token. Предусловия - Клиент должен передать валидный Bearer token. - Token должен содержать company context. - Token должен содержать scope employees.write. - idCompany не передаётся отдельно. - employeeId должен принадлежать сотруднику в рамках текущего tenant-а. Запрос Path parameters | Параметр | Тип | Обязательный | Описание | | ------------ | ------- | ---------------- | -------------- | | employeeId | int64 | да | ID сотрудника. | curl пример Удалить сотрудника curl -X DELETE 'https://smartway.pro/api/v1/employees/4432' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Ответ Успешный ответ: 204 No Content. Успешный ответ не содержит body. Поля ответа Delete response | Элемент | Тип | Описание | | ------------- | -------------- | --------------------------- | | HTTP status | 204 No Content | Операция выполнена успешно. | | Response body | отсутствует | Body не возвращается. | Бизнес-логика - BFF берёт companyId из Bearer token, а не из параметров запроса. - Endpoint удаляет сотрудника только в рамках текущего tenant-контекста. - Для доступа нужен scope employees.write. Edge cases Edge cases | Сценарий | Поведение API | | --------------------------------------- | -------------------------------------------------------- | | employeeId не найден в текущем tenant-е | API возвращает 404 Not Found. | | Bearer token без employees.write | API возвращает 403 Forbidden. | | Операция успешна | API возвращает 204 No Content без body. | | Клиент передаёт idCompany | Endpoint не использует idCompany из клиентского запроса. | Ошибки Error responses | HTTP status | Когда возникает | | ------------------------- | ------------------------------------------------ | | 401 Unauthorized | Bearer token отсутствует или невалиден. | | 403 Forbidden | Недостаточно прав или token без company context. | | 404 Not Found | Сотрудник не найден в рамках текущего tenant-а. | | 500 Internal Server Error | Неожиданная ошибка BFF. | | 503 Service Unavailable | Сбой внутренней интеграции BFF -> back2. | Использование - Удалить сотрудника из LMS Smart Way через интеграцию. - Очистить тестовые записи после проверки интеграции. - Убрать сотрудника, который больше не должен находиться в employee dataset. Типичные ошибки Typical integration mistakes | Типичная ошибка | Как правильно | | -------------------------------------- | ------------------------------------------------------------ | | Ожидать JSON в ответе | Успешный ответ — 204 No Content без body. | | Передавать idCompany | Не передавайте idCompany; companyId берётся из Bearer token. | | Использовать token без employees.write | Для DELETE нужен scope employees.write. | FAQ Что возвращает API после успешного удаления? 204 No Content без response body. Нужно ли передавать idCompany? Нет. companyId берётся из Bearer token. Что будет, если employeeId не найден? API вернёт 404 Not Found.

Обновлено May 03, 2026

Получить каталог тестов

GET /v1/tests возвращает каталог тестов, доступных текущей компании: системные тесты и собственные тесты компании. Integrated synthetic-тесты SCORM/CMI5/xAPI в ответ не входят. Endpoint | Метод | URL | | --------- | ----------------------------------- | | GET | https://smartway.pro/api/v1/tests | Назначение Получить список тестов, которые можно использовать для тестирования кандидатов или сотрудников. Предварительные условия | Требование | Значение | | -------------- | -------------------------------------- | | Авторизация | Authorization: Bearer <access_token> | | Scope | tests.read | | Tenant context | Определяется сервером из Bearer token | | idCompany | Не передаётся внешним клиентом | Запрос Параметры не передаются. curl пример curl -X GET 'https://smartway.pro/api/v1/tests' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Ответ Успешный ответ: 200 OK. { "data": [ { "testId": 5, "name": "Conflict Test", "active": true, "companyOwned": false, "questionCount": 30 }, { "testId": 200001, "name": "Adaptive Sales", "active": true, "companyOwned": true, "questionCount": 12 } ], "meta": { "total": 2 } } Поля ответа | Поле | Тип | Описание | | ---------------------- | -------- | ---------------------------------------------- | | data | object[] | Список тестов, доступных текущей компании | | data[].testId | int64 | ID теста | | data[].name | string | Название теста | | data[].active | boolean | Признак активности теста | | data[].companyOwned | boolean | true, если тест принадлежит текущей компании | | data[].questionCount | int32 | Количество вопросов в тесте | | meta.total | int32 | Общее количество тестов в ответе | Бизнес-логика - Компания определяется из Bearer token. - Возвращаются системные тесты и тесты, принадлежащие текущей компании. - Поле companyOwned показывает, принадлежит ли тест текущей компании. Пограничные случаи | Сценарий | Поведение API | | --------------------------------------------------------- | ------------------------------ | | Тест является integrated synthetic-тестом SCORM/CMI5/xAPI | Тест не входит в каталог | | В токене нет company context | API возвращает 403 Forbidden | Ошибки | HTTP status | Причина | | ------------------------- | ----------------------------------------------- | | 401 Unauthorized | Bearer token отсутствует или невалиден | | 403 Forbidden | Недостаточно прав или токен без company context | | 500 Internal Server Error | Неожиданная ошибка LMS Smart Way | | 503 Service Unavailable | Сбой внутренней интеграции LMS Smart Way | Использование Используйте endpoint, чтобы получить доступные testId перед созданием приглашения или настройкой фильтров отчётов. Типичные ошибки | Ошибка | Как избежать | | ---------------------------------------------------- | ----------------------------------------------------------- | | Использование токена без tests.read | Проверьте scope API key | | Передача idCompany в запросе | Не передавайте idCompany; компания определяется из токена | | Ожидание SCORM/CMI5/xAPI synthetic-тестов в каталоге | Этот endpoint такие тесты не возвращает | FAQ Нужно ли передавать idCompany? Нет. Компания определяется сервером из Bearer token. Входят ли SCORM/CMI5/xAPI synthetic-тесты в ответ? Нет. Они не входят в каталог GET /v1/tests.

Обновлено Apr 27, 2026

Получить тест по ID

GET /v1/tests/{testId} возвращает детальную информацию о тесте, если он доступен текущей компании и не является integrated synthetic-тестом SCORM/CMI5/xAPI. Endpoint | Метод | URL | | --------- | -------------------------------------------- | | GET | https://smartway.pro/api/v1/tests/{testId} | Назначение Получить настройки конкретного теста: активность, количество вопросов, таймер, уникальность, валидацию и проходной балл. Предварительные условия | Требование | Значение | | -------------- | --------------------------------------------------------- | | Авторизация | Authorization: Bearer <access_token> | | Scope | tests.read | | Tenant context | Поиск выполняется в рамках tenant context из Bearer token | Запрос Path parameters | Параметр | Тип | Обязательный | Описание | | ------------ | ------- | ---------------- | ------------ | | testId | int64 | да | ID теста | curl пример curl -X GET 'https://smartway.pro/api/v1/tests/200001' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Ответ Успешный ответ: 200 OK. { "testId": 200001, "name": "Adaptive Sales", "active": true, "companyOwned": true, "questionCount": 12, "timerEnabled": true, "timerMinutes": 10, "uniquenessEnabled": true, "uniquenessQuestionCount": 25, "validationEnabled": true, "passingScore": 75 } Поля ответа | Поле | Тип | Описание | | ------------------------- | ------- | ---------------------------------------------- | | testId | int64 | ID теста | | name | string | Название теста | | active | boolean | Признак активности теста | | companyOwned | boolean | true, если тест принадлежит текущей компании | | questionCount | int32 | Количество вопросов в тесте | | timerEnabled | boolean | Включён ли таймер | | timerMinutes | int32 | Длительность таймера в минутах | | uniquenessEnabled | boolean | Включена ли уникальность вопросов | | uniquenessQuestionCount | int32 | Количество уникальных вопросов | | validationEnabled | boolean | Включена ли валидация результата | | passingScore | int32 | Проходной балл | Бизнес-логика - API ищет тест в рамках tenant context из Bearer token. - Если тест недоступен текущей компании, API возвращает 404 Not Found. - Integrated synthetic-тесты SCORM/CMI5/xAPI через этот endpoint не возвращаются. Пограничные случаи | Сценарий | Поведение API | | ------------------------------------------------------------------------------ | -------------------------------------- | | Тест недоступен текущей компании | 404 Not Found | | testId принадлежит integrated synthetic-тесту SCORM/CMI5/xAPI | 404 Not Found | | Настройки таймера, уникальности, валидации или проходного балла не применяются | Соответствующие поля могут быть null | Ошибки | HTTP status | Причина | | ------------------------- | ------------------------------------------------------------------------------------- | | 401 Unauthorized | Bearer token отсутствует или невалиден | | 403 Forbidden | Недостаточно прав | | 404 Not Found | Тест не найден, недоступен текущему tenant-у или является integrated synthetic-тестом | | 500 Internal Server Error | Неожиданная ошибка LMS Smart Way | | 503 Service Unavailable | Сбой внутренней интеграции LMS Smart Way | Использование Используйте endpoint после GET /v1/tests, чтобы получить детали конкретного теста перед созданием приглашения или анализом настроек. Типичные ошибки | Ошибка | Как избежать | | ----------------------------------------------------- | ---------------------------------------- | | Использование testId, недоступного текущей компании | Получайте testId через GET /v1/tests | | Обработка nullable-полей как обязательных | Проверяйте null для настроек теста | FAQ Почему API возвращает 404 Not Found для существующего testId? Тест может быть недоступен текущей компании или относиться к integrated synthetic-тестам SCORM/CMI5/xAPI. Все ли настройки теста всегда заполнены? Нет. Часть настроек может быть null.

Обновлено Apr 27, 2026

Как получить список отчётов по тестированию через API

Краткий ответ Endpoint POST /api/v1/tests/reports/search возвращает список отчётов по тестированию с применением текущего сохранённого фильтра. Все поля request body необязательны; без body API использует page = 0, size = 50, view = all. Для доступа нужен Bearer token со scope tests.read, а lang может управлять языком локализованных ресурсов тестирования. Какой endpoint используется? Используется POST /api/v1/tests/reports/search. Endpoint возвращает страницу отчётов по тестированию в рамках компании с учётом текущего сохранённого фильтра. | Параметр | Значение | | ------------ | ------------------------------ | | Method | POST | | Endpoint | /api/v1/tests/reports/search | | Base URL | https://smartway.pro | | Auth | Bearer token | | Content-Type | application/json | Для чего используется этот API endpoint? Endpoint используется для получения отчётов по тестированию компании с пагинацией, режимом представления и поиском по ФИО. Его применяют HR-интеграции, backend-сервисы и технические администраторы для построения списков отчётов и перехода к PDF-отчётам. Какие предварительные условия нужны перед выполнением запроса? - Нужен Bearer token с company context. - Token должен содержать scope tests.read. - Перед получением нужных данных нужно учитывать текущий сохранённый фильтр или сбросить его. | Предусловие | Описание | Обязательно | | ------------------ | -------------------------------------------------------------------------- | --------------- | | access_token | Bearer token с company context | Да | | tests.read | Scope для чтения отчётов по тестированию | Да | | Сохранённый фильтр | Фильтр из GET/PUT /api/v1/tests/reports/filter применяется дополнительно | Нет | Какие параметры нужно передать в запросе? Headers | Header | Тип | Обязательно | Описание | | --------------- | ------- | ------------------------ | ---------------------------------------------- | | Authorization | string | Да | Bearer token в формате Bearer <access_token> | | Accept | string | Да | application/json | | Content-Type | string | Да, если передаётся body | application/json | Path parameters Path parameters отсутствуют. Query parameters | Параметр | Тип | Обязательно | Описание | | ------------ | ------- | --------------- | ----------------------------------------------------------------------------------------- | | lang | string | Нет | Язык локализованных ресурсов тестирования; default en, доступные языки uk, ru, en | Request body | Параметр | Тип | Обязательно | Описание | | ------------ | ------- | --------------- | -------------------------------------------------------------- | | page | int32 | Нет | Номер страницы; default 0; параметр 0-based | | size | int32 | Нет | Размер страницы; default 50, максимум 200 | | view | string | Нет | Режим выборки; допустимы только all, candidate, employee | | query | string | Нет | Поиск по ФИО | curl-пример Пример вызова без body: curl -X POST 'https://smartway.pro/api/v1/tests/reports/search' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Пример вызова с параметрами: curl -X POST 'https://smartway.pro/api/v1/tests/reports/search?lang=ru' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "page": 0, "size": 20, "view": "all", "query": "Иван" }' Какой ответ возвращает API? Успешный запрос возвращает 200 OK и объект PublicTestReportListResponse со списком отчётов и метаданными пагинации. { "data": [ { "uniqueId": "abc12345", "candidateId": 1001, "name": "Иван Петренко", "dateSend": "2026-03-10", "dateReceipt": "2026-03-12", "active": true, "testNames": "Conflict Test, Adaptive Sales", "department": "Sales", "jobTitle": "Manager" } ], "meta": { "page": 0, "size": 20, "totalElements": 1, "totalPages": 1, "hasNext": false } } Что означают поля в ответе API? | Поле | Тип | Описание | | -------------------- | ------- | ----------------------------------------------- | | data[].uniqueId | string | Уникальный идентификатор отчёта по тестированию | | data[].candidateId | integer | ID кандидата | | data[].name | string | ФИО кандидата или сотрудника | | data[].dateSend | string | Дата отправки тестирования | | data[].dateReceipt | string | Дата получения результата | | data[].active | boolean | Признак активности отчёта | | data[].testNames | string | Названия тестов в отчёте | | data[].department | string | Департамент | | data[].jobTitle | string | Должность | | meta.page | integer | Номер текущей страницы | | meta.size | integer | Размер страницы | | meta.totalElements | integer | Общее количество элементов | | meta.totalPages | integer | Общее количество страниц | | meta.hasNext | boolean | Признак наличия следующей страницы | Что происходит под капотом? - Tenant-видимость отчётов определяется server-side по companyId в Bearer token как company-level / HRADMIN-equivalent scope. - Отчётность не ограничивается кандидатами, приглашёнными через текущий API key или HR-владельца ключа. - API возвращает все отчёты по тестированию компании, доступные HRADMIN-уровню. - Дополнительно применяется текущий сохранённый фильтр из GET/PUT /api/v1/tests/reports/filter: active, startDate, endDate, testIds, departments, jobTitles. - lang необязателен; если его не передать, API использует en. - Для доступа нужен scope tests.read. Какие edge cases нужно учитывать? | Сценарий | Поведение API | Что сделать интегратору | | -------------------------- | ---------------------------------------------------- | ---------------------------------------------------- | | Запрос без body | API использует page = 0, size = 50, view = all | Не передавать body, если нужны значения по умолчанию | | Нумерация страниц | page является 0-based | Передавать page = 0 для первой страницы | | Невалидный view | API возвращает 400 Bad Request | Использовать только all, candidate, employee | | Сохранённый фильтр активен | Фильтр применяется дополнительно | Перед поиском настроить или сбросить фильтр | | lang не передан | API использует en | Передать lang, если нужен другой язык | Какие ошибки может вернуть API? | HTTP status | Описание | | --------------------------- | -------------------------------------------------------- | | 400 Bad Request | Невалидный view или другие невалидные параметры поиска | | 401 Unauthorized | Отсутствует или невалидный Bearer token | | 403 Forbidden | Недостаточно прав | | 500 Internal Server Error | Неожиданная ошибка | | 503 Service Unavailable | Сбой внутренней интеграции | Как использовать результат в следующих API-запросах? Используйте meta.page, meta.size, meta.totalPages и meta.hasNext для пагинации. Значение uniqueId из списка используется для получения PDF-отчёта. Пример следующего запроса для получения PDF-отчёта: curl -X GET 'https://smartway.pro/api/v1/tests/reports/pdf?uniqueId=abc12345&lang=ru' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/pdf' \ --output test-report-abc12345.pdf Каких ошибок интегратору стоит избегать? - Считать page = 1 первой страницей. - Не учитывать активный сохранённый фильтр перед поиском. - Передавать view, отличный от all, candidate, employee. - Ожидать, что API вернёт только отчёты кандидатов, приглашённых через текущий API key. FAQ Обязательно ли передавать request body? Нет. Если вызвать endpoint без body, API использует page = 0, size = 50, view = all. С какой страницы начинается пагинация? Параметр page является 0-based: page = 0 — первая страница, page = 1 — вторая. Какие значения поддерживает view? Допустимы только all, candidate, employee. Применяется ли сохранённый фильтр? Да. Дополнительно применяется фильтр из GET/PUT /api/v1/tests/reports/filter. Какой scope нужен? Для доступа нужен scope tests.read.

Обновлено May 03, 2026

Как получить PDF-отчёт результатов тестирования через API

Endpoint GET /api/v1/tests/reports/pdf возвращает PDF-отчёт тестирования по uniqueId. В query нужно передать uniqueId, а lang можно передать для выбора языка PDF-отчёта. Перед выдачей PDF сервер проверяет, что отчёт принадлежит текущей компании. Какой endpoint используется? Используется GET /api/v1/tests/reports/pdf. Endpoint возвращает binary PDF file по уникальному идентификатору отчёта по тестированию. | Параметр | Значение | | ------------ | --------------------------- | | Method | GET | | Endpoint | /api/v1/tests/reports/pdf | | Base URL | https://smartway.pro | | Auth | Bearer token | Для чего используется этот API endpoint? Endpoint используется для загрузки или открытия PDF-отчёта тестирования. Его применяют после получения uniqueId из списка отчётов по тестированию. Какие предварительные условия нужны перед выполнением запроса? - Нужен Bearer token с company context. - Token должен содержать scope tests.read. - Нужен uniqueId отчёта по тестированию, принадлежащего текущей компании. | Предусловие | Описание | Обязательно | | --------------- | ----------------------------------------------- | --------------- | | access_token | Bearer token с company context | Да | | tests.read | Scope для чтения отчётов по тестированию | Да | | uniqueId | Уникальный идентификатор отчёта по тестированию | Да | Какие параметры нужно передать в запросе? Headers | Header | Тип | Обязательно | Описание | | --------------- | ------- | --------------- | ---------------------------------------------- | | Authorization | string | Да | Bearer token в формате Bearer <access_token> | | Accept | string | Да | application/pdf | Path parameters Path parameters отсутствуют. Query parameters | Параметр | Тип | Обязательно | Описание | | ------------ | ------- | --------------- | --------------------------------------------------------------- | | uniqueId | string | Да | Уникальный идентификатор отчёта по тестированию | | lang | string | Нет | Язык PDF-отчёта; default en, доступные языки uk, ru, en | Request body Request body не используется. curl-пример curl -X GET 'https://smartway.pro/api/v1/tests/reports/pdf?uniqueId=abc12345&lang=ru' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/pdf' \ --output test-report-abc12345.pdf Какой ответ возвращает API? Успешный запрос возвращает 200 OK и binary PDF file. Успешный ответ содержит Content-Type: application/pdf и Content-Disposition: inline; filename=test-report-<uniqueId>.pdf. JSON response body не используется, потому что ответ является binary PDF file. Что означают поля в ответе API? Недостаточно данных для описания полей ответа. Что происходит под капотом? - Перед выдачей PDF сервер проверяет, что отчёт принадлежит текущей компании. - Для доступа нужен scope tests.read. Какие edge cases нужно учитывать? | Сценарий | Поведение API | Что сделать интегратору | | ------------------------------------- | ------------------------------ | ----------------------------------------------------------------------------- | | uniqueId не найден | API возвращает 404 Not Found | Проверить uniqueId из списка отчётов по тестированию | | Отчёт не принадлежит текущей компании | API возвращает 404 Not Found | Использовать только uniqueId, доступные в tenant-контексте текущей компании | | lang не передан | API использует en | Передать lang, если нужен другой язык PDF | Какие ошибки может вернуть API? | HTTP status | Описание | | --------------------------- | --------------------------------------------------- | | 401 Unauthorized | Отсутствует или невалидный Bearer token | | 403 Forbidden | Недостаточно прав | | 404 Not Found | Отчёт не найден или не принадлежит текущей компании | | 500 Internal Server Error | Неожиданная ошибка | | 503 Service Unavailable | Сбой сервиса | Как использовать результат в следующих API-запросах? Значение uniqueId берётся из ответа POST /api/v1/tests/reports/search. Результат PDF-запроса нужно сохранять в файл или открывать как PDF-документ. Пример получения uniqueId из списка отчётов: curl -X POST 'https://smartway.pro/api/v1/tests/reports/search?lang=ru' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "page": 0, "size": 20, "view": "all" }' Каких ошибок интегратору стоит избегать? - Передавать uniqueId, который не принадлежит текущей компании. - Не указывать Accept: application/pdf. - Ожидать JSON-ответ вместо binary PDF file. - Вызывать endpoint без scope tests.read. FAQ Какой параметр обязателен? Обязательный query parameter — uniqueId. Какой язык PDF можно запросить? Параметр lang поддерживает uk, ru, en; если его не передать, используется en. Что возвращает API? API возвращает binary PDF file с Content-Type: application/pdf. Что будет, если отчёт не принадлежит компании? API вернёт 404 Not Found. Какой scope нужен? Для доступа нужен scope tests.read.

Обновлено May 03, 2026

Как получить сохранённый фильтр отчётов по тестированию через API

Endpoint GET /api/v1/tests/reports/filter возвращает сохранённый фильтр отчётов по тестированию для userKey, который берётся из subject Bearer token. Для company API key этот userKey имеет формат company-api-key:{companyId} и остаётся стабильным после ротации ключа. Для доступа нужен Bearer token со scope tests.read. Какой endpoint используется? Используется GET /api/v1/tests/reports/filter. Endpoint возвращает текущий сохранённый фильтр отчётов по тестированию для user context из Bearer token. | Параметр | Значение | | ------------ | ------------------------------ | | Method | GET | | Endpoint | /api/v1/tests/reports/filter | | Base URL | https://smartway.pro | | Auth | Bearer token | Для чего используется этот API endpoint? Endpoint используется для просмотра текущего фильтра, который применяется к поиску и экспорту отчётов по тестированию. Его используют перед POST /api/v1/tests/reports/search или POST /api/v1/tests/reports/export, чтобы понять, какие ограничения будут применены. Какие предварительные условия нужны перед выполнением запроса? | Предусловие | Описание | Обязательно | | --------------- | ------------------------------------- | --------------- | | access_token | Bearer token | Да | | tests.read | Scope для чтения сохранённого фильтра | Да | Какие параметры нужно передать в запросе? Headers | Header | Тип | Обязательно | Описание | | --------------- | ------- | --------------- | ---------------------------------------------- | | Authorization | string | Да | Bearer token в формате Bearer <access_token> | | Accept | string | Да | application/json | Path parameters Path parameters отсутствуют. Query parameters Query parameters отсутствуют. Request body Request body не используется. curl-пример curl -X GET 'https://smartway.pro/api/v1/tests/reports/filter' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Какой ответ возвращает API? Успешный запрос возвращает 200 OK и объект PublicTestReportFilterResponse с параметрами сохранённого фильтра. { "active": true, "startDate": "2026-03-01", "endDate": "2026-03-10", "groupByName": true, "testIds": [5, 200001], "departments": ["Sales"], "jobTitles": ["Manager"] } Что означают поля в ответе API? | Поле | Тип | Описание | | ------------- | ------- | ------------------------------------------------ | | active | boolean | Фильтр по признаку активности отчёта | | startDate | string | Начало диапазона дат | | endDate | string | Конец диапазона дат | | groupByName | boolean | Группировка нескольких попыток прохождения теста | | testIds | array | Набор ID тестов для фильтра | | departments | array | Набор департаментов для фильтра | | jobTitles | array | Набор должностей для фильтра | Что происходит под капотом? - Фильтр привязан к userKey, который берётся из subject Bearer token. - Для company API key userKey имеет формат company-api-key:{companyId}. - userKey стабилен после ротации ключа. - Внешний клиент не передаёт idUser. - Для доступа нужен scope tests.read. Какие edge cases нужно учитывать? | Сценарий | Поведение API | Что сделать интегратору | | --------------------------- | --------------------------------------------------------------------- | ----------------------------------------------- | | Ротация company API key | userKey остаётся стабильным в формате company-api-key:{companyId} | Не создавать отдельную привязку к active key id | | idUser в запросе | Внешний клиент не передаёт idUser | Не добавлять idUser в query string или body | | Активный сохранённый фильтр | Фильтр применяется к поиску и экспорту | Проверять фильтр перед получением отчётов | Какие ошибки может вернуть API? | HTTP status | Описание | | --------------------------- | --------------------------------------- | | 401 Unauthorized | Отсутствует или невалидный Bearer token | | 403 Forbidden | Недостаточно прав | | 500 Internal Server Error | Неожиданная ошибка | | 503 Service Unavailable | Сбой сервиса | Как использовать результат в следующих API-запросах? Используйте полученный фильтр, чтобы понять, какие ограничения будут применены к POST /api/v1/tests/reports/search и POST /api/v1/tests/reports/export. Пример поиска отчётов после проверки фильтра: curl -X POST 'https://smartway.pro/api/v1/tests/reports/search' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Каких ошибок интегратору стоит избегать? - Передавать idUser в запросе. - Ожидать, что фильтр привязан к конкретному active key id. - Запускать поиск или экспорт без проверки текущего фильтра. - Вызывать endpoint без scope tests.read. FAQ К чему привязан сохранённый фильтр? Фильтр привязан к userKey, который берётся из subject Bearer token. Какой формат userKey у company API key? Для company API key userKey имеет формат company-api-key:{companyId}. Нужно ли передавать idUser? Нет. Внешний клиент не передаёт idUser. Изменится ли фильтр после ротации ключа? Для company API key userKey стабилен после ротации ключа. Какой scope нужен? Для доступа нужен scope tests.read.

Обновлено May 04, 2026

Как обновить или очистить фильтр отчётов по тестированию через API

Endpoint PUT /api/v1/tests/reports/filter обновляет или очищает сохранённый фильтр отчётов по тестированию. В request body можно передать active, диапазон дат, groupByName, testIds, departments и jobTitles; если передать {} или body только с null/пустыми коллекциями, сервер очищает фильтр. Для доступа нужен Bearer token со scope tests.write. Какой endpoint используется? Используется PUT /api/v1/tests/reports/filter. Endpoint изменяет сохранённый фильтр отчётов по тестированию для user context из Bearer token. | Параметр | Значение | | ------------ | ------------------------------ | | Method | PUT | | Endpoint | /api/v1/tests/reports/filter | | Base URL | https://smartway.pro | | Auth | Bearer token | | Content-Type | application/json | Для чего используется этот API endpoint? Endpoint используется для управления фильтром, который применяется к поиску и экспорту отчётов по тестированию. Его используют перед получением списка отчётов или перед формированием Excel-экспорта. Какие предварительные условия нужны перед выполнением запроса? - Нужен Bearer token. - Token должен содержать scope tests.write. | Предусловие | Описание | Обязательно | | --------------- | ----------------------------------------- | --------------- | | access_token | Bearer token | Да | | tests.write | Scope для обновления сохранённого фильтра | Да | Какие параметры нужно передать в запросе? Headers | Header | Тип | Обязательно | Описание | | --------------- | ------- | --------------- | ---------------------------------------------- | | Authorization | string | Да | Bearer token в формате Bearer <access_token> | | Accept | string | Да | application/json | | Content-Type | string | Да | application/json | Path parameters Path parameters отсутствуют. Query parameters Query parameters отсутствуют. Request body | Параметр | Тип | Обязательно | Описание | | ------------- | ------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------- | | active | boolean | Нет | Фильтр по признаку активности отчёта | | startDate | string (date) | Нет | Начало диапазона дат | | endDate | string (date) | Нет | Конец диапазона дат | | groupByName | boolean | Нет | Группировка нескольких попыток прохождения теста в одну строку с максимальным результатом и указанным количеством попыток | | testIds | int64[] | Нет | Набор ID тестов для фильтра | | departments | string[] | Нет | Набор департаментов для фильтра | | jobTitles | string[] | Нет | Набор должностей для фильтра | curl-пример Пример вызова с обновлением фильтра: curl -X PUT 'https://smartway.pro/api/v1/tests/reports/filter' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "active": true, "startDate": "2026-03-01", "endDate": "2026-03-10", "groupByName": true, "testIds": [5, 200001], "departments": ["Sales"], "jobTitles": ["Manager"] }' Пример вызова для очистки фильтра: curl -X PUT 'https://smartway.pro/api/v1/tests/reports/filter' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{}' Какой ответ возвращает API? Успешный запрос возвращает 200 OK и объект PublicTestReportFilterResponse с актуальным состоянием фильтра. { "active": true, "startDate": "2026-03-01", "endDate": "2026-03-10", "groupByName": true, "testIds": [5, 200001], "departments": ["Sales"], "jobTitles": ["Manager"] } Что означают поля в ответе API? | Поле | Тип | Описание | | ------------- | ------- | ------------------------------------------------ | | active | boolean | Фильтр по признаку активности отчёта | | startDate | string | Начало диапазона дат | | endDate | string | Конец диапазона дат | | groupByName | boolean | Группировка нескольких попыток прохождения теста | | testIds | array | Набор ID тестов для фильтра | | departments | array | Набор департаментов для фильтра | | jobTitles | array | Набор должностей для фильтра | Что происходит под капотом? - Фильтр привязан к userKey, который берётся из subject Bearer token. - Для company API key userKey имеет формат company-api-key:{companyId}. - Обновление фильтра не привязано к конкретному active key id. - Внешний клиент не передаёт idUser. - Если передать пустой объект {} или body только с null/пустыми коллекциями, сервер очищает фильтр. - Если endDate < startDate, API возвращает 400 Bad Request. - Для доступа нужен scope tests.write. Какие edge cases нужно учитывать? | Сценарий | Поведение API | Что сделать интегратору | | -------------------------------------------- | --------------------------------------------------- | ------------------------------------------- | | Пустой body {} | Сервер очищает фильтр | Передавать {}, если нужно сбросить фильтр | | Body только с null или пустыми коллекциями | Сервер очищает фильтр | Использовать для очистки фильтра | | endDate < startDate | API возвращает 400 Bad Request | Проверять диапазон дат перед запросом | | Ротация company API key | Обновление не привязано к конкретному active key id | Не создавать зависимость от active key id | Какие ошибки может вернуть API? | HTTP status | Описание | | --------------------------- | -------------------------------------------------------------- | | 400 Bad Request | Невалидный диапазон дат или другие невалидные значения фильтра | | 401 Unauthorized | Отсутствует или невалидный Bearer token | | 403 Forbidden | Недостаточно прав | | 500 Internal Server Error | Неожиданная ошибка | | 503 Service Unavailable | Сбой сервиса | Как использовать результат в следующих API-запросах? После обновления или очистки фильтра следующие запросы к поиску и экспорту отчётов по тестированию будут выполняться с учётом актуального фильтра. Пример поиска отчётов после обновления фильтра: curl -X POST 'https://smartway.pro/api/v1/tests/reports/search' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Каких ошибок интегратору стоит избегать? - Передавать idUser в request body или query string. - Передавать endDate, который меньше startDate. - Ожидать, что фильтр привязан к конкретному active key id. - Забывать, что пустой {} очищает фильтр. - Вызывать endpoint без scope tests.write. FAQ Как очистить фильтр? Передайте пустой JSON-объект {} или body только с null/пустыми коллекциями. Что будет, если endDate < startDate? API вернёт 400 Bad Request. Нужно ли передавать idUser? Нет. idUser внешний клиент не передаёт. Какой scope нужен? Для доступа нужен scope tests.write. К чему привязан фильтр? Фильтр привязан к userKey, который берётся из subject Bearer token.

Обновлено May 03, 2026

Как отправить кандидату приглашение на тестирование через API

Endpoint POST /api/v1/tests/invitations/candidates создаёт HR-приглашение кандидату на тестирование. В body нужно передать имя, фамилию, email, gender и список testIds; sendCopyToHr является необязательным. Параметр lang управляет языком письма-приглашения и языком ссылки на прохождение теста. Какой endpoint используется? Используется POST /api/v1/tests/invitations/candidates. Endpoint создаёт приглашение кандидату на прохождение одного или нескольких тестов. | Параметр | Значение | | ------------ | -------------------------------------- | | Method | POST | | Endpoint | /api/v1/tests/invitations/candidates | | Base URL | https://smartway.pro | | Auth | Bearer token | | Content-Type | application/json | Для чего используется этот API endpoint? Endpoint используется для отправки HR-приглашения кандидату на тестирование. Его применяют в рекрутинговых интеграциях, когда внешняя система передаёт кандидата и список тестов для прохождения. Какие предварительные условия нужны перед выполнением запроса? - Нужен Bearer token с company context. - Token должен содержать scope tests.write. - Нужен хотя бы один активный testId, доступный текущей компании. | Предусловие | Описание | Обязательно | | --------------- | ------------------------------ | --------------- | | access_token | Bearer token с company context | Да | | tests.write | Scope для создания приглашения | Да | | testIds | Список ID активных тестов | Да | Какие параметры нужно передать в запросе? Headers | Header | Тип | Обязательно | Описание | | --------------- | ------- | --------------- | ---------------------------------------------- | | Authorization | string | Да | Bearer token в формате Bearer <access_token> | | Accept | string | Да | application/json | | Content-Type | string | Да | application/json | Path parameters Path parameters отсутствуют. Query parameters | Параметр | Тип | Обязательно | Описание | | ------------ | ------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | lang | string | Нет | Язык приглашения. Поддерживаются uk, ru, en. Если параметр отсутствует или передано другое значение, сервер использует en. | Request body | Параметр | Тип | Обязательно | Описание | | -------------- | ------- | --------------- | ------------------------------------------------------------------------------------ | | name | string | Да | Имя кандидата | | surname | string | Да | Фамилия кандидата | | email | string | Да | Email кандидата | | gender | string | Да | Допустимы только значения Male или Female | | testIds | int64[] | Да | Список ID тестов; должен содержать хотя бы один элемент | | sendCopyToHr | boolean | Нет | Если true, сервер дополнительно отправляет копию приглашения на HR email из токена | curl-пример curl -X POST 'https://smartway.pro/api/v1/tests/invitations/candidates?lang=ru' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "name": "Иван", "surname": "Петренко", "email": "candidate@company.test", "gender": "Male", "testIds": [5, 200001], "sendCopyToHr": true }' Какой ответ возвращает API? Успешный запрос возвращает 202 Accepted. Что происходит под капотом? - idCompany не передаётся в body или query string: он будет взят из Bearer token. - hrEmail не передаётся внешним клиентом: он будет взят из Bearer token. - lang принимает только uk, ru, en; если параметр не передан или значение не поддерживается, приглашение отправляется на английском (en). - gender принимает только Male или Female. - testIds должен содержать хотя бы один элемент. - Перед созданием приглашения сервер проверяет каждый testId: тест должен существовать и быть активным. - Если в запросе есть несколько невалидных testIds, API возвращает один 400 Bad Request с перечнем всех проблемных элементов. - Для доступа нужен scope tests.write. Какие edge cases нужно учитывать? | Сценарий | Поведение API | Что сделать интегратору | | --------------------------------------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------- | | lang отсутствует или не поддерживается | Сервер использует en | Передавать uk, ru или en, если нужен конкретный язык | | gender не Male или Female | API возвращает 400 Bad Request | Передавать только Male или Female | | testIds пустой | API возвращает 400 Bad Request | Передавать хотя бы один testId | | Один или несколько testIds не существуют либо неактивны | API возвращает один 400 Bad Request с перечнем всех проблемных testId | Предварительно проверять testIds через каталог или детали теста | Какие ошибки может вернуть API? | HTTP status | Описание | | --------------------------- | -------------------------------------------------------------------------------------------------------------------------- | | 400 Bad Request | Отсутствует required-параметр, gender не равен Male / Female, или хотя бы один testId не существует либо неактивен | | 401 Unauthorized | Отсутствует или невалидный Bearer token | | 403 Forbidden | Недостаточно прав | | 500 Internal Server Error | Неожиданная ошибка | | 503 Service Unavailable | Сбой сервиса | Пример error response: { "type": "https://smartway.pro/problems/public-api", "title": "Bad Request", "status": 400, "detail": "Candidate invitation contains invalid testIds: testId 2 does not exist; testId 3 is inactive.", "instance": "/api/v1/tests/invitations/candidates" } Как использовать результат в следующих API-запросах? Перед созданием приглашения получите доступные testId через каталог тестов. Полученные testIds передавайте в body запроса в массиве testIds. Пример получения каталога тестов перед созданием приглашения: curl -X GET 'https://smartway.pro/api/v1/tests' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Каких ошибок интегратору стоит избегать? - Передавать idCompany или hrEmail в body. - Передавать gender в значениях, отличных от Male или Female. - Передавать пустой testIds. - Использовать неактивные или несуществующие testIds. - Ожидать ошибку для неподдерживаемого lang, хотя API использует en. FAQ Какой status возвращается при успешном создании приглашения? API возвращает 202 Accepted. Нужно ли передавать idCompany? Нет. idCompany будет взят из Bearer token. Откуда берётся HR email? hrEmail будет взят из Bearer token; внешний клиент его не передаёт. Какие значения поддерживает gender? Допустимы только Male или Female. Что будет, если несколько testIds невалидны? API вернёт один 400 Bad Request с перечнем всех проблемных элементов.

Обновлено May 03, 2026

Как отправить сотрудникам приглашение на тестирование через API

Endpoint POST /api/v1/tests/invitations/employees выполняет массовую рассылку сотрудникам приглашений на тестирование. В body нужно передать непустые массивы employeeIds и testIds. Параметр lang управляет языком писем-приглашений и языком ссылок на прохождение теста. Какой endpoint используется? Используется POST /api/v1/tests/invitations/employees. Endpoint отправляет приглашение на тестирование списку сотрудников. | Параметр | Значение | | ------------ | ------------------------------------- | | Method | POST | | Endpoint | /api/v1/tests/invitations/employees | | Base URL | https://smartway.pro | | Auth | Bearer token | | Content-Type | application/json | Для чего используется этот API endpoint? Endpoint используется для массовой рассылки приглашений на тестирование сотрудникам компании. Его применяют в HR-интеграциях, когда внешняя система имеет список сотрудников и список тестов. Какие предварительные условия нужны перед выполнением запроса? - Нужен Bearer token с company context. - Token должен содержать scope tests.write. - Нужен хотя бы один employeeId в рамках текущей компании. - Нужен хотя бы один testId. | Предусловие | Описание | Обязательно | | --------------- | ------------------------------ | --------------- | | access_token | Bearer token с company context | Да | | tests.write | Scope для создания приглашений | Да | | employeeIds | Список ID сотрудников | Да | | testIds | Список ID тестов | Да | Какие параметры нужно передать в запросе? Headers | Header | Тип | Обязательно | Описание | | --------------- | ------- | --------------- | ---------------------------------------------- | | Authorization | string | Да | Bearer token в формате Bearer <access_token> | | Accept | string | Да | application/json | | Content-Type | string | Да | application/json | Path parameters Path parameters отсутствуют. Query parameters | Параметр | Тип | Обязательно | Описание | | ------------ | ------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | lang | string | Нет | Язык приглашения. Поддерживаются uk, ru, en. Если параметр отсутствует или передано другое значение, сервер использует en. | Request body | Параметр | Тип | Обязательно | Описание | | ------------- | ------- | --------------- | ------------------------------------------------------------ | | employeeIds | int64[] | Да | Список ID сотрудников; должен содержать хотя бы один элемент | | testIds | int64[] | Да | Список ID тестов; должен содержать хотя бы один элемент | curl-пример curl -X POST 'https://smartway.pro/api/v1/tests/invitations/employees?lang=en' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "employeeIds": [101, 102], "testIds": [5, 200001] }' Какой ответ возвращает API? Успешный запрос возвращает 202 Accepted. Что происходит под капотом? - idCompany не передаётся в body или query string: он будет получен из Bearer token. - hrEmail не передаётся внешним клиентом: он будет получен из Bearer token. - lang принимает только uk, ru, en; если параметр не передан или значение не поддерживается, приглашения отправляются на английском (en). - employeeIds и testIds должны содержать хотя бы один элемент. - Если хотя бы один employee отсутствует в рамках текущей компании, API возвращает 404 Not Found. - Для доступа нужен scope tests.write. Какие edge cases нужно учитывать? | Сценарий | Поведение API | Что сделать интегратору | | ------------------------------------------- | -------------------------------- | ------------------------------------------------------------- | | lang отсутствует или не поддерживается | Сервер использует en | Передавать uk, ru или en, если нужен конкретный язык | | employeeIds пустой | API возвращает 400 Bad Request | Передавать хотя бы один employeeId | | testIds пустой | API возвращает 400 Bad Request | Передавать хотя бы один testId | | Хотя бы один сотрудник не найден в tenant-е | API возвращает 404 Not Found | Проверять, что все employeeIds принадлежат текущей компании | Какие ошибки может вернуть API? | HTTP status | Описание | | --------------------------- | ----------------------------------------------------------- | | 400 Bad Request | Отсутствуют или пустые employeeIds / testIds | | 401 Unauthorized | Отсутствует или невалидный Bearer token | | 403 Forbidden | Недостаточно прав | | 404 Not Found | Хотя бы один сотрудник не найден в рамках текущего tenant-а | | 500 Internal Server Error | Неожиданная ошибка | | 503 Service Unavailable | Сбой сервиса | Как использовать результат в следующих API-запросах? Перед массовой рассылкой получите доступные testId через каталог тестов. В body передавайте сотрудников в employeeIds, а тесты — в testIds. Пример получения каталога тестов: curl -X GET 'https://smartway.pro/api/v1/tests' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Каких ошибок интегратору стоит избегать? - Передавать idCompany или hrEmail в body. - Передавать пустой employeeIds или testIds. - Передавать employeeIds, которые не принадлежат текущей компании. - Ожидать ошибку для неподдерживаемого lang, хотя API использует en. - Вызывать endpoint без scope tests.write. FAQ Какой status возвращается при успешной рассылке? API возвращает 202 Accepted. Нужно ли передавать idCompany? Нет. idCompany будет получен из Bearer token. Что будет, если один сотрудник не найден? API вернёт 404 Not Found, если хотя бы один сотрудник не найден в рамках текущего tenant-а. Какие массивы обязательны? Обязательны непустые employeeIds и testIds. Какой scope нужен? Для доступа нужен scope tests.write.

Обновлено May 03, 2026