Внешнее API

Документ описывает внешние API SmartCPD, поддерживаемые в текущем релизе:

  • Prometheus API для чтения метрик;
  • Markup API для загрузки фактических результатов вызовов из клиентского контура;
  • IDM API v2 для управления сотрудниками и получения ролей;
  • Audit API v2 для чтения платформенного журнала аудита.

Авторизация#

Для авторизации во внешних API используются управляемые API-ключи SmartCPD.

Для подготовки доступа необходимо:

  1. Создать в портале отдельную роль для интеграции.
  2. Назначить роли привилегии, необходимые вызываемым методам.
  3. В разделе API ключи создать API-ключ и назначить ему подготовленную роль.
  4. Скопировать выданный токен и сохранить его в защищенном хранилище интеграции.

Токен отображается только при создании или ротации API-ключа и передается в каждом запросе:

Authorization: Bearer API_KEY

API-ключ создается в контексте клиента. Доступ к tenant-scoped методам ограничивается клиентом API-ключа и его tenant scope. Доступ к каждому методу дополнительно ограничивается привилегиями назначенных ролей.

Для управления API-ключами пользователю портала требуются следующие привилегии:

ОперацияПривилегия
Просмотр API-ключейapiKey.canSee
Создание, изменение, ротация, отзыв и удаление API-ключейapiKey.canEdit
Назначение ролей API-ключуemployee.role.canEdit
Назначение административных ролейemployee.role.canEdit и employee.role.admin.canEdit

Общие коды ошибок авторизации:

КодОписание
401 UnauthorizedBearer-токен отсутствует, недействителен, отозван или просрочен
403 ForbiddenУ API-ключа нет требуемой привилегии или доступа к указанному клиенту

Prometheus API#

Prometheus API предоставляет доступ к метрикам SmartCPD через публичный адрес портала и путь /prometheus/.

Требуемая привилегия: metrics.canSee.

Пример запроса:

curl -ik \
  -H "Authorization: Bearer API_KEY" \
  'https://portal.fqdn/prometheus/api/v1/query?query=up'

Публично доступны только методы Prometheus, расположенные под /prometheus/api/.

Markup API#

Markup API загружает фактические результаты вызовов от операторов или внешних систем заказчика и связывает их с вызовами CDR.

Требуемая привилегия: cdr.canEdit.

Разметка может связываться с вызовом:

  • по SIP Call-ID;
  • по Custom Call ID;
  • по номеру клиента и времени вызова.

Методы#

МетодНазначение
POST /api/cdr/v1/markupЗагрузка JSON для клиента API-ключа
POST /api/cdr/v1/markup/csvЗагрузка CSV для клиента API-ключа
POST /api/cdr/v1/tenant/{tenant_inn}/markupЗагрузка JSON для указанного клиента
POST /api/cdr/v1/tenant/{tenant_inn}/markup/csvЗагрузка CSV для указанного клиента

Методы с tenant_inn дополнительно проверяют доступ API-ключа к указанному клиенту.

Загрузка JSON#

POST /api/cdr/v1/markup
Authorization: Bearer API_KEY
Content-Type: application/json

Тело запроса содержит непустой массив записей:

[
  {
    "call_id": "51f737c0-4de5-0139-ba9f-0ac31e3255d2",
    "call_id_type": "sip",
    "ts": "2026-07-17T11:29:05Z",
    "result": "human",
    "original_result": "человек принял звонок",
    "source": "operator-system"
  }
]

Состав полей, их обязательность, формат и допустимые значения приведены в едином справочнике «Поля разметки».

Ограничения запроса:

  • размер тела — не более 10 MiB;
  • количество записей — не более 10 000;
  • размер каждого строкового поля — не более 4 KiB;
  • дополнительные неизвестные поля не допускаются;
  • все временные значения преобразуются и сохраняются в UTC.

Записи обрабатываются последовательно. Полностью успешный запрос возвращает 200 OK:

{
  "accepted_count": 2
}

Если часть записей отклонена или не обработана после внутренней ошибки, API возвращает 207 Multi-Status:

{
  "accepted_count": 1,
  "rejected": [
    {
      "index": 2,
      "record": {
        "call_id": "missing-call",
        "call_id_type": "sip",
        "ts": "2026-07-17T11:30:00Z",
        "result": "robot"
      },
      "reason": "not_found"
    }
  ],
  "unprocessed": []
}

index — номер записи в исходном массиве, начиная с 1. rejected содержит записи, отклоненные по ожидаемой причине. unprocessed содержит текущую и оставшиеся записи, которые не удалось обработать после внутренней ошибки.

Статусы и все значения reason описаны в справочнике «Коды обработки».

Коды ответа JSON-загрузки:

КодОписание
200 OKВсе записи приняты
207 Multi-StatusЕсть отклоненные или не обработанные записи
400 Bad RequestНекорректный JSON, пустой массив или нарушение структуры запроса
401 UnauthorizedAPI-ключ отсутствует или недействителен
403 ForbiddenНет cdr.canEdit или доступа к указанному клиенту
413 Content Too LargeПревышен лимит тела, количества записей или размера поля
415 Unsupported Media TypeContent-Type отличается от application/json
500 Internal Server ErrorОбработка не началась из-за внутренней ошибки

Загрузка CSV#

POST /api/cdr/v1/markup/csv
Authorization: Bearer API_KEY
Content-Type: text/csv; charset=utf-8

Состав обязательных столбцов и правила заполнения значений приведены в справочнике «Поля разметки». Дополнительные столбцы, кроме служебных upload_status и reason, не поддерживаются.

CSV должен быть в кодировке UTF-8. Другие кодировки, включая Windows-1251, не поддерживаются; файл нужно пересохранить в UTF-8 до отправки. Параметр charset не выполняет перекодирование. При невалидном UTF-8 сервер возвращает 400 Bad Request с JSON-полем error, содержащим invalid UTF-8 string и расположение проблемного поля; ни одна запись из файла не обрабатывается.

Для CSV действуют те же ограничения тела, количества записей, размера полей и допустимых значений, что и для JSON. Дополнительно размер одной строки CSV ограничен 64 KiB. До начала загрузки файл полностью проверяется на корректность структуры и кодировки UTF-8.

Ответы 200 OK и 207 Multi-Status имеют формат CSV и содержат только отклоненные и не обработанные строки. В ответ добавляются или заменяются столбцы:

СтолбецЗначение
upload_statusrejected или unprocessed
reasonПричина обработки из справочника «Коды обработки»

Полученный файл можно исправить и загрузить повторно.

Заголовки успешного ответа и ответа с частичным результатом:

ЗаголовокОписание
Content-Type: text/csv; charset=utf-8Формат ответа
Content-Disposition: attachment; filename="markup-problems.csv"Имя возвращаемого файла
X-Accepted-CountКоличество принятых строк
X-Rejected-CountКоличество отклоненных строк
X-Unprocessed-CountКоличество не обработанных строк

Коды ответа CSV-загрузки:

КодОписание
200 OKВсе строки приняты; возвращается CSV без проблемных строк
207 Multi-StatusВозвращается CSV с отклоненными или не обработанными строками
400 Bad RequestНевалидная кодировка UTF-8, некорректная структура CSV или отсутствует обязательный столбец
401 UnauthorizedAPI-ключ отсутствует или недействителен
403 ForbiddenНет cdr.canEdit или доступа к указанному клиенту
413 Content Too LargeПревышен лимит тела, количества строк, строки или поля
415 Unsupported Media TypeContent-Type отличается от text/csv
500 Internal Server ErrorОбработка не началась из-за внутренней ошибки

IDM API v2#

IDM API v2 управляет учетными записями сотрудников и предоставляет сведения о ролях. API поддерживает on-premise и multitenant/cloud-сценарии.

Операции с сотрудниками выполняются в контексте клиента, заданного параметром tenant_inn. API-ключ должен иметь доступ к указанному клиенту.

Методы и привилегии#

МетодНазначениеПривилегия
GET /api/v2/tenant/{tenant_inn}/idm/usersПолучение сотрудников клиентаemployee.canSee
GET /api/v2/idm/rolesПолучение ролейrole.canSee
POST /api/v2/tenant/{tenant_inn}/idm/employeeСоздание сотрудникаemployee.canEdit
PATCH /api/v2/tenant/{tenant_inn}/idm/employeeИзменение сотрудникаemployee.canEdit
POST /api/v2/tenant/{tenant_inn}/idm/employee/blockБлокировка сотрудникаemployee.canEdit
POST /api/v2/tenant/{tenant_inn}/idm/employee/unblockРазблокировка сотрудникаemployee.canEdit
POST /api/v2/tenant/{tenant_inn}/idm/employee/passwordСмена пароля сотрудникаemployee.password.canEdit

Для назначения обычных ролей сотруднику дополнительно требуется employee.role.canEdit. Для назначения административных ролей также требуется employee.role.admin.canEdit.

Получение сотрудников#

GET /api/v2/tenant/{tenant_inn}/idm/users
Authorization: Bearer API_KEY

Ответ содержит сотрудников указанного клиента:

[
  {
    "login": "user@example.com",
    "name": "Иванов Иван Иванович",
    "status": "active",
    "roles": ["support"],
    "privileges": ["employee.canSee"],
    "last_login_time": "2026-07-17T10:30:00Z",
    "last_change_password": "2026-07-10T08:15:00Z",
    "login_ip_address": "192.0.2.10"
  }
]

Возможные статусы сотрудника:

  • active — активный сотрудник.
  • not_active — неактивный сотрудник (административный статус).
  • banned — заблокирован. Устанавливается методом блокировки IDM API и снимается только методом разблокировки IDM API.
  • temporary_banned — временно заблокирован. Устанавливается системой безопасности после превышения лимита неуспешных попыток входа. Снимается при успешном входе после тайм-аута, вручную через IDM API unblock или через UI пользователем с привилегией employee.canEdit в пределах доступного tenant.

banned и temporary_banned — это security-статусы. Для temporary_banned в UI предусмотрено отдельное действие «Снять временную блокировку»; banned через UI не снимается.

Получение ролей#

GET /api/v2/idm/roles
Authorization: Bearer API_KEY

Пример ответа:

[
  {
    "id": 21,
    "name": "idm-api",
    "privileges": [
      "employee.canSee",
      "employee.canEdit",
      "employee.password.canEdit",
      "employee.role.canEdit",
      "role.canSee"
    ]
  }
]

Создание сотрудника#

POST /api/v2/tenant/{tenant_inn}/idm/employee
Authorization: Bearer API_KEY
Content-Type: application/json

Пример запроса:

{
  "username": "Иванов Иван",
  "email": "user@example.com",
  "tel": "79999999999",
  "password": "SHA512_HASH",
  "agreed": true,
  "email_deal": false,
  "roles": ["support"]
}

password содержит SHA-512-хеш пароля в шестнадцатеричном представлении. После создания сотрудник должен сменить пароль при первом входе.

Если пароль при создании сотрудника не соответствует требованиям безопасности, сервер возвращает 422 Unprocessable Entity с JSON-полем message, содержащим причину отказа («Слишком слабый пароль…»). Сотрудник не создаётся.

Поле roles содержит имена ролей, возвращаемые методом получения ролей. При успешном создании API возвращает:

{
  "code": 0
}

Изменение сотрудника#

PATCH /api/v2/tenant/{tenant_inn}/idm/employee
Authorization: Bearer API_KEY
Content-Type: application/json

Поиск сотрудника выполняется по обязательному полю login. Остальные поля задают новые значения:

{
  "login": "user@example.com",
  "username": "Иванов Петр",
  "tel": "79999999998",
  "roles": ["support"]
}

roles содержит полный итоговый список ролей сотрудника. Пароль и системные поля этим методом не изменяются.

Блокировка сотрудника#

POST /api/v2/tenant/{tenant_inn}/idm/employee/block
Authorization: Bearer API_KEY
Content-Type: application/json

{
  "login": "user@example.com"
}

После успешной блокировки статус сотрудника становится banned («Заблокирован»).

Разблокировка сотрудника#

POST /api/v2/tenant/{tenant_inn}/idm/employee/unblock
Authorization: Bearer API_KEY
Content-Type: application/json

{
  "login": "user@example.com"
}

После успешной разблокировки статус сотрудника становится active («Активный»).

Смена пароля сотрудника#

POST /api/v2/tenant/{tenant_inn}/idm/employee/password
Authorization: Bearer API_KEY
Content-Type: application/json

{
  "login": "user@example.com",
  "password": "SHA512_HASH"
}

password содержит SHA-512-хеш нового пароля в шестнадцатеричном представлении. После выполнения операции сотрудник должен сменить пароль при следующем входе.

Коды ответа IDM API#

КодОписание
200 OKОперация выполнена
400 Bad RequestНекорректный запрос
401 UnauthorizedAPI-ключ отсутствует или недействителен
403 ForbiddenНет требуемой привилегии или доступа к клиенту
404 Not FoundКлиент, сотрудник или роль не найдены
409 ConflictКонфликт состояния или уникальности данных
422 Unprocessable EntityЗапрос не соответствует схеме или пароль при создании сотрудника не соответствует требованиям безопасности
500 Internal Server ErrorВнутренняя ошибка сервиса

Изменения сотрудников и паролей записываются в журнал аудита.

Audit API v2#

В текущем релизе внешний Audit API предоставляет доступ только к платформенному журналу аудита. Tenant-scoped доступ к аудиту не входит в поддерживаемый внешний контракт.

Требуемая привилегия: audit.canSee.

Получение платформенного журнала#

GET /api/v2/platform/audit
Authorization: Bearer API_KEY

Параметры запроса:

ПараметрОписание
pageНомер страницы, начиная с 1; значение по умолчанию — 1
per_pageКоличество записей на странице от 1 до 200; значение по умолчанию — 10
textПоиск по содержимому записи, не более 500 символов
from_date, from_timeНачало временного интервала
to_date, to_timeКонец временного интервала

Пример ответа:

{
  "items": [
    {
      "id": 125,
      "operation": "change_roles",
      "entity": "employee",
      "body": "изменение ролей сотрудника user@example.com",
      "object_inn": "1234567890",
      "object_type": "employee",
      "datetime": "2026-07-17T10:30:00Z",
      "username": "integration@example.com"
    }
  ]
}

Коды ответа:

КодОписание
200 OKЗапрос выполнен
401 UnauthorizedAPI-ключ отсутствует или недействителен
403 ForbiddenНет привилегии audit.canSee
422 Unprocessable EntityНекорректные параметры запроса
500 Internal Server ErrorВнутренняя ошибка сервиса

Дата формирования

Powered by Altuera