Перейти к основному содержимому

Интеграционный API

Все доступные операции с объектами OMNI Platform можно реализовать с помощью интеграционного API. Доступ к API обеспечивается через GraphQL - язык запросов и манипулирования данными API с открытым исходным кодом, а также среды выполнения существующих запросов данных. GraphQL позволяет отправлять запросы на OMNI Platform и получать ответные данные, которые можно интегрировать в ваше собственное приложение. Более подробно о GraphQL смотрите по ссылкам:

Для начала работы с API войдите в свой аккаунт на OMNI Platform. Для создания аккаунта перейдите на страницу регистрации.

На главной странице веб-интерфейса нажмите на кнопку Platform API в виджете Ресурсы для перехода в интерактивную консоль GraphQL.

Для использования интеграционного API в вашем приложении добавьте токен в заголовок HTTP-запроса и отправьте запрос на https://cloud.3divi.ai/api/v2/. Для получения токена выполните следующие шаги:

  1. Откройте интерактивную консоль GraphQL, кликнув на кнопку Platform API в виджете Ресурсы на главной странице веб-интерфейса.
  2. Скопируйте указанный ниже запрос в консоль и нажмите Выполнить запрос.
query{
me {
workspaces {
accesses {
id
}
}
}
}
  1. В результате GraphQL вернет ответ, который содержит токен (id):
{
"data": {
"me": {
"workspaces": [
{
"accesses ": [
{
"id": "3460***"
}
]
}
]
}
}
}

Пользователь, зарегистрированный под PLATFORM_DEFAULT_EMAIL, может получить токен доступа к API через следующую команду:

$ ./setup/get-token.sh

С более подробной информацией по получению и использованию токена можно ознакомиться в Руководстве администратора.

cURL-запросы

Помимо GraphQL запросы можно отправлять с помощью cURL. cURL-шаблон для отправки API запросов указан ниже:

curl --location --request POST "<url>" --header "token: <ваш токен доступа>" --header "Content-Type: application/json" --data-raw "{\"query\":\"<GraphQL query or mutation>\",\"variables\":{<GraphQL variables>}}"

<url> - URL вашего сервера

<ваш токен доступа> - без указания токена доступа ваши cURL-запросы не смогут быть отправлены.

Пример cURL-запроса: С помощью даного запроса можно получить список 5 первых профилей из базы.

curl --location --request POST "<IntegrationAPIUrl/>" --header "token: 3e357***" --header "Content-Type: application/json" --data-raw "{\"query\":\"query {profiles(limit: 5, offset: 0) {totalCount, collectionItems {id, info}}}\",\"variables\":{}}"

API возвращает следующий результат:

{
"data": {
"profiles": {
"totalCount": 5,
"collectionItems": [
{
"id": "195ed5fe-580e-476f-8496-befdb0003d85",
"info": {
"age": 46,
"gender": "MALE",
"avatar_id": "9945328f-ebd8-4683-bde5-25284686f439",
"main_sample_id": "83800c22-5ed3-4c9f-91bf-ce79c0de747a"
}
},
{
"id": "8d46bf22-5d24-4e4f-bfd3-e215cbde53f0",
"info": {
"age": 24,
"gender": "FEMALE",
"avatar_id": "1e7c8293-75e8-485a-8861-415eec854011",
"main_sample_id": "6cbd4c9a-7cd0-4c43-9561-387be9dff6f3"
}
},
{
"id": "944ab599-bd6d-47bf-b8e3-ed201a4e6530",
"info": {
"age": 31,
"gender": "MALE",
"avatar_id": "9f36bee0-efdf-42fc-a059-c60d5c7e6da9",
"main_sample_id": "db9998a4-4331-41b5-9abd-30499b881be8"
}
},
{
"id": "aa40fb31-96d3-421b-96ae-05566fc57bee",
"info": {
"age": 35,
"gender": "MALE",
"avatar_id": "ae61ec9f-2953-4f24-86d8-7718df6f9ff5",
"main_sample_id": "33a72136-175b-4361-8444-e1e0c4ce04d4"
}
},
{
"id": "c5e1b7d9-b446-4739-a3d0-a8cf8d717c70",
"info": {
"age": 21,
"gender": "MALE",
"avatar_id": "9938407f-d101-4005-8d30-4b1ce8319bc7",
"main_sample_id": "f2b3d23a-6f73-4d9b-97aa-13edaf5e82f7"
}
}
]
}
}
}

Запросы и ответы для тестирования API в GraphQL указаны ниже.

Распознавание лиц

Общие ошибки входных данных

Ошибки при загрузке изображения через API:

  • Неверная строка base64:
{
"message": "image file is truncated (21 bytes not processed)"
}
  • Изображение представлено не в формате base64:
{
"message": "Expected value of type 'CustomBinaryType', found \"wrong_data\";
}
  • Изображение не передано:
{
"message": "Sample Data is not valid",
"code": "0xc69c44d4"
}
  • Неверный формат изображения:
{
"message": "Image decode failed"
}
  • Изображение без лиц:
{
"message": "No faces found",
"code": "0x95bg42fd"
}
  • Слишком большой размер изображения:
Bad Request (400)

Ошибки при фильтрации, пагинации и сортировке сущностей:

  • Переданные фильтры не поддерживают формат словаря:
{
"message": "'str' object has no attribute 'keys'"
}
  • Неверное поле фильтрации:
{
"message": "Cannot resolve keyword '' into field. Choices are: creation_date, id, info, last_modified, link_to_label, person, person_id, profile_groups, samples, workspace, workspace_id"
}
  • Неверное поле для фильтрации подобхъектов или фильтрации поля по функции:
{
"message": "Unsupported lookup '1' for UUIDField or join on the field not permitted."
}
  • Отрицательное значение в поле пагинации:
{
"message": "Negative indexing is not supported."
}
  • Неверное поле сортировки:
{
"message": "Cannot resolve keyword '' into field. Choices are: creation_date, id, info, last_modified, link_to_label, person, person_id, profile_groups, samples, workspace, workspace_id"
}

Другие общие ошибки:

  • ID объекта не задан в формате UUID:
{
"message": "“%(value)s” is not a valid UUID."
}
  • Переданный JSON не прошел валидацию по JSON-схеме:
{
"message": "Invalid JSON request"
}

Детекция и обработка лиц

Запрос позволяет обнаружить несколько лиц на изображении, определить атрибуты лиц (пол, возраст, эмоции, liveness, наличие маски и др.) и создавать сэмплы данных.

processImage(image: CustomBinaryType!): ImageProcessInfo!

image: CustomBinaryType!: Изображение в формате base64

ImageProcessInfo!: API возвращает файл в формате JSON, который содержит следующие поля:

faces:[FaceProcessInfo!]!: Данные детекции и обработки лиц представлены следующими полями:

  • id: Int!: Уникальный идентификационный номер лица на изображении
  • class: String!: Класс объекта. Данный API-запрос работает только с объектами класса "лицо"
  • confidence: Float!: Числовое значение уверенности детекции
  • bbox: [Float!]!: Координаты ограничивающего прямоугольника вокруг лица. Расчитываются относительно координат исходного изображения. Первые две bbox-координаты - X и Y левой верхней точки, вторые две - X и Y правой нижней точки
  • cropImage: String!: Изображение лица в формате base64, вырезанное из исходного изображения по расширенным границам bbox
  • fitter: Fitter!: Антропометрические точки
    • fitter_type:: Вид набора антропометрических точек. Набор fda обеспечивает высокое качество в широком диапазоне ракурсов (вплоть до профильных), при этом алгоритмы распознавания по-прежнему требуют, чтобы ракурс лица был максимально приближен к фронтальному. Набор fda содержит 21 точку
    • keypoints: Антропометрические точки лица. Список координат (X, Y, Z) точек относительно исходного изображения
    • left_eye: Координаты (X, Y) точки центра левого глаза, рассчитанные относительно границ исходного изображения
    • right_eye: Координаты (X, Y) точки центра правого глаза, рассчитанные относительно границ исходного изображения
  • emotions: [Emotions!]! Оценка эмоций по изображению лица
    • confidence: String! Числовое значение проявления каждой эмоции
    • emotion: String! Тип эмоции: гнев (angry), отвращение (disgusted), страх (scared), счастье (happy), нейтральное выражение лица (neutral), грусть (sad), удивление (surprised)
  • mask: MaskConfidenceValue! Оценка наличия/отсутствия маски на лице
    • confidence: String! Числовое значение уверенности наличия/отсутствия маски на лице
    • value: Boolean! Вердикт: true - человек в маске, false - человек без маски
  • templates: Templates! Биометрический шаблон, закодированный в base64
  • gender: String! Определение пола человека по изображению лица
  • age: String! Определение возраста человека по изображению лица
  • angles: Angles! Углы наклона и поворота головы. Алгоритмы 3DiVi выполняют детекцию лиц в следующем диапазоне углов: yaw [-60; 60], pitch [-60; 60], roll [-30; 30]
    • yaw: String! Вращение по вертикальной оси Y
    • roll: String! Вращение по горизонтальной оси X
    • **pitch: String! Вращение по горизонтальной оси Z
  • liveness: LivenessConfidenceValue! Оценка принадлежности изображения реальному человеку
    • confidence: String! Числовое значение уверенности принадлежности изображения реальному человеку
    • value: String! вердикт: REAL - на изображении реальный человек, FAKE - изображение не принадлежит реальному человеку
  • quality: Quality! Оценка качества изображения
    • qaa: Qaa! Алгоритм оценки качества (Quality assessment algorithm) оперирует следующими данными:
      • totalScore: Int! Численное значение, обозначает общую оценку качества изображения в баллах от 0 до 100
      • isSharp: Boolean! Логическое значение, обозначает резкость изображения
      • sharpnessScore: Int! Числовое значение, обозначает оценку резкости в баллах от 0 до 100
      • isEvenlyIlluminated: Boolean! Логическое значение, обозначает равномерность освещения на изображении
      • illuminationScore: Int! Числовое значение, оценка равномерности освещения в баллах от 0 до 100
      • noFlare: Boolean! Логическое значение, указывает на наличие или отсутствие вспышек на изображении
      • isLeftEyeOpened: Boolean! Логическое значение, обозначает положение левого глаза (открыт/закрыт)
      • leftEyeOpennessScore: Int! Числовое значение, обозначает степень открытости глаза в баллах от 0 до 100
      • isRightEyeOpened: Boolean! Логическое значение, обозначает положение правого глаза (открыт/закрыт)
      • rightEyeOpennessScore: Int! Числовое значение, обозначает степень открытости глаза в баллах от 0 до 100
      • isRotationAcceptable: Boolean! Логическое значение, обозначает допустимый/недопустимый наклон или поворот головы
      • maxRotationDeviation: Int! Числовое значение, максимальный градус отклонения для трех (yaw, pitch, roll) углов наклона и поворота головы
      • notMasked: Boolean! Логическое значение, указывает на наличие/отсутствие маски на лице
      • notMaskedScore: Int! Числовое значение, обозначает степень уверенности в отсутствии маски на лице от 0 до 100
      • isNeutralEmotion: Boolean! Логическое значение, обозначает наличие/отсутствие нейтрального выражения лица
      • neutralEmotionScore: Int! Числовое значение, оценка степени нейтральных эмоций в баллах от 0 до 100
      • isEyesDistanceAcceptable: Boolean! Логическое значение, обозначает допустимое/ недопустимое расстояние между глазами
      • eyesDistance: Int! Численное значение расстояния между глазами в px
      • isMarginsAcceptable: Boolean! Логическое значение, обозначает допустимые/недопустимые отступы
      • marginOuterDeviation: Int! Числовое значение внешнего отклонения в px
      • marginInnerDeviation: Int! Числовое значение внутреннего отклонения в px
      • isNotNoisy: Boolean! Логическое значение, обозначает наличие/отсутствие шумов на изображении
      • noiseScore: Int! Числовое значение, оценка зашумленности изображения в баллах от 0 до 100
      • watermarkScore: Int! Численное значение, обозначает степень уверенности в наличии водяного знака на изображении от 0 до 100
      • hasWatermark: Boolean! Логическое значение, указывает на наличие/отсутствие водяного знака на изображении
      • dynamicRangeScore: Int! Числовое значение, оценка динамического диапазона интенсивности в баллах от 0 до 100
      • isDynamicRangeAcceptable: Boolean! Логическое значение, показывает, что динамический диапазон интенсивности изображения в области лица превышает/не превышает значение 128
      • isBackgroundUniform: Boolean! Логическое значение, указывает на однородность фона
      • backgroundUniformityScore: Int! Числовое значение, оценка однородности фона в баллах от 0 до 100

sample:JSON! Результат детекции и обработки лица в формате сэмпла данных. Сэмпл содержит загруженное изображение в формате base64 и список вышеперечисленных полей faces.

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

query{
processImage(image:"Your image in base64 format")
{faces{
id
class
age
bbox
fitter {
fitterType
keypoints
leftEye
rightEye
}
}
sample
}
}

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

API возвращает следующий результат:
  {
"data": {
"processImage": {
"faces": [
{
"id": 0,
"class": "face",
"age": "27",
"bbox": [
0.3551912568306011,
0.23272727272727273,
0.6666666666666666,
0.43272727272727274
],
"fitter": {
"fitterType": "fda",
"keypoints": [
75.72225189208984,
74.6084976196289,
0,
77.31121063232422,
74.45097351074219,
0,
80.28999328613281,
76.27693939208984,
0,
87.48872375488281,
77.59190368652344,
0,
92.68600463867188,
77.93761444091797,
0,
97.7556381225586,
80.83274841308594,
0,
75.1549301147461,
80.66946411132812,
0,
77.28436279296875,
81.22076416015625,
0,
79.21238708496094,
81.67471313476562,
0,
88.30126953125,
83.95287322998047,
0,
91.18292236328125,
84.60287475585938,
0,
95.00492858886719,
85.73049926757812,
0,
71.32847595214844,
93.35795593261719,
0,
74.99060821533203,
93.20181274414062,
0,
74.82111358642578,
92.45048522949219,
0,
83.24044799804688,
94.2305908203125,
0,
111.6617202758789,
104.77130889892578,
0,
73.94023895263672,
100.82368469238281,
0,
77.04241943359375,
102.39466094970703,
0,
87.22122192382812,
103.42082214355469,
0,
73.90850830078125,
116.2977294921875,
0
],
"leftEye": [
77.28436279296875,
81.22076416015625
],
"rightEye": [
91.18292236328125,
84.60287475585938
]
}
}
],
"sample": {
"$image": "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",
"objects": [
{
"id": 0,
"class": "face",
"age": 27,
"confidence": 0.8873210549354553,
"fitter": {
"fitter_type": "fda",
"keypoints": [
75.72225189208984,
74.6084976196289,
0,
77.31121063232422,
74.45097351074219,
0,
80.28999328613281,
76.27693939208984,
0,
87.48872375488281,
77.59190368652344,
0,
92.68600463867188,
77.93761444091797,
0,
97.7556381225586,
80.83274841308594,
0,
75.1549301147461,
80.66946411132812,
0,
77.28436279296875,
81.22076416015625,
0,
79.21238708496094,
81.67471313476562,
0,
88.30126953125,
83.95287322998047,
0,
91.18292236328125,
84.60287475585938,
0,
95.00492858886719,
85.73049926757812,
0,
71.32847595214844,
93.35795593261719,
0,
74.99060821533203,
93.20181274414062,
0,
74.82111358642578,
92.45048522949219,
0,
83.24044799804688,
94.2305908203125,
0,
111.6617202758789,
104.77130889892578,
0,
73.94023895263672,
100.82368469238281,
0,
77.04241943359375,
102.39466094970703,
0,
87.22122192382812,
103.42082214355469,
0,
73.90850830078125,
116.2977294921875,
0
],
"left_eye": [
77.28436279296875,
81.22076416015625
],
"right_eye": [
91.18292236328125,
84.60287475585938
]
},
"bbox": [
0.3551912568306011,
0.23272727272727273,
0.6666666666666666,
0.43272727272727274
],
"$crop_image": "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",
"angles": {
"yaw": -40.34304428100586,
"roll": 12.045698165893555,
"pitch": -16.30009651184082
}
}
]
}
}
}
}

Детекция лиц

Этот запрос позволяет обнаружить несколько лиц на изображении и получить информацию об этих лицах (например, пол, возраст, эмоции, liveness, наличие маски и т. д.). В качестве ответа вы получаете результат детекции без возможности его сохранения в локальной базе данных.

Внимание! Поддержка данного API-запроса действует до 2024 года.

detect(image: CustomBinaryType!pupils:
[EyesInput!] = null): JSON!

image: CustomBinaryType!: Изображение в формате base64
pupils: [EyesInput!]: Для повышения точности детекции можно указать X и Y координаты зрачков.

  • EyesInput!
    • leftPupil: PointInputType!
      • x: Float!
      • y: Float!
    • rightPupil: PointInputType!
      • x: Float!
      • y: Float!

JSON! : API возвращает сэмпл в формате JSON со следующими параметрами:

  • image: Изображение в формате base64
  • id: Порядковый номер лица на изображении
  • class: Имя класса объекта, например, лицо
  • template: Уникальный набор биометрических характеристик, извлеченных из изображения лица. Шаблоны используются для сравнения двух изображений лиц и определения степени сходства.
  • bbox: Прямоугольная рамка вокруг лица, которая показывает положение и размер лица на исходном изображении.
  • crop image: Система обрезает загруженное изображение с целью извлечения изображений лиц. Такое извлеченное изображение лица и называется crop image.
  • keypoints: Набор из 21 точки лица, указывающих на положение частей лица.
  • rotation angles: Углы вращения: Yaw (вращение по оси Z), pitch (вращение по оси Y) и roll (вращение по оси X)Алгоритм позволяет обнаруживать лица в следующем диапазоне углов: yaw [-60; 60], pitch [-60; 60], roll [-30; 30]
  • age: Возраст в годах
  • gender: Пол персоны на изображении
  • emotions: Эмоции по степени достоверности
  • liveness: Встроенный liveness-алгоритм, который позволяет определить, что на фотографии изображен реальный человек.
  • mask presence: Параметр наличия маски на лице.

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

query{
detect(image:"your image in Base64 format")
}

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

API возвращает следующий результат:
  {
"data": {
"detect": {
"$image": "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",
"objects@common_capturer_uld_fda": [
{
"id": 1,
"class": "face",
"templates": {
"$template10v100": "T5JnWgcfMPHQANMdP8NA8FwPQJLc5TDfcJFVFS/tYgEw9yNCISDQAiGU9iVQDwAA0BM6AhOQAcorXw5b/msC0AzwvQJfO34SzSACyQ9qYvom8gAMAHQP3lBgyQB/weXffCAPC1bUxw4GA10E8DADewH70SNzBsBdCwQRDyAPNTAfAOHjEAICAuQSAR8uEjQPVBIB3j2xCbDuTbAdIMGRLgAhFwIfDdQlUcID/w4/LfDvMEABQOEn4w8uBvAeFz/k0UAgA/QjDwESnA/0cDzAE9UCAO61JwEjEgAvINNRDhkdCUEg5UEO9ycL9FHzNBGSAmxABf4GK3QCnSFh8SAQAUIRJAWxTCQVAAHF4E1SIBAfIn2eMReb0g=="
},
"bbox": [
0,
0.21308482869466144,
1,
0.9869169769287109
],
"$cropImage": "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",
"keypoints": {
"left_eye_brow_left": {
"x": 0.1554061550564236,
"y": 0.3466766866048177
},
"left_eye_brow_up": {
"x": 0.25802788628472223,
"y": 0.3236322784423828
},
"left_eye_brow_right": {
"x": 0.3854702419704861,
"y": 0.3430420430501302
},
"right_eye_brow_left": {
"x": 0.6136109754774306,
"y": 0.345932362874349
},
"right_eye_brow_up": {
"x": 0.7370150417751736,
"y": 0.3286321258544922
},
"right_eye_brow_right": {
"x": 0.8359405517578125,
"y": 0.35814239501953127
},
"left_eye_left": {
"x": 0.21608330620659721,
"y": 0.4157813008626302
},
"left_pupil": {
"x": 0.30088453504774304,
"y": 0.4109149678548177
},
"left_eye_right": {
"x": 0.3838650173611111,
"y": 0.4230572001139323
},
"right_eye_left": {
"x": 0.6079323323567708,
"y": 0.4287389628092448
},
"right_pupil": {
"x": 0.6891607666015624,
"y": 0.4170384724934896
},
"right_eye_right": {
"x": 0.7724110243055555,
"y": 0.4233682759602865
},
"left_ear_bottom": {
"x": 0.1043272230360243,
"y": 0.5988115437825521
},
"nose_left": {
"x": 0.3953646511501736,
"y": 0.5805702209472656
},
"nose": {
"x": 0.4884576416015625,
"y": 0.5780504862467448
},
"nose_right": {
"x": 0.5848392740885416,
"y": 0.5861359659830729
},
"right_ear_bottom": {
"x": 0.8565327962239583,
"y": 0.607865956624349
},
"mouth_left": {
"x": 0.33830030653211807,
"y": 0.6955980936686198
},
"mouth": {
"x": 0.4904075113932292,
"y": 0.7090469868977864
},
"mouth_right": {
"x": 0.6333636474609375,
"y": 0.6958428955078125
},
"chin": {
"x": 0.4895579020182292,
"y": 0.8763695271809896
}
},
"age": 23,
"emotions": {
"neutral": 0.9834117889404297,
"angry": 0.013813868165016174,
"happy": 0.002322095213457942,
"surprised": 0.00045228638919070363
},
"gender": "FEMALE",
"liveness": {
"value": "FAKE",
"confidence": 0.801980197429657
},
"angles": {
"yaw": -0.8611235618591309,
"pitch": -15.951218605041504,
"roll": 1.7437981367111206
},
"mask": {
"value": false,
"confidence": 1
}
}
]

}
}
}

Создание сэмпла

Мутация позволяет создавать сэмплы с атрибутами лиц (пола, возраста, эмоций, ключевых точек, liveness, наличия маски и т.д.).Созданный сэмпл автоматически сохраняется на OMNI-сервере.

createSample(
anonymousMode: Boolean = false
image: CustomBinaryType = null
pupils: [EyesInput!] = null
sampleData: JSON = null): [SampleOutput!]!

anonymousMode: Boolean = false : При работе с анонимными данными можно установить для anonymousMode значение true (по умолчанию установлено значение false). В этом случае изображение не будет храниться на OMNI-сервере.

image: CustomBinaryType : Изображение в формате base64

pupils: [EyesInput!] : Для повышения точности детекции лиц можно установить X и Y координаты зрачков.

  • EyesInput!
    • leftPupil: PointInputType!
      • x: Float!
      • y: Float!
    • rightPupil: PointInputType!
      • x: Float!
      • y: Float!

sampleData: JSON : Результат детекции лица, не сохраненный в базе.

SampleOutput! : API возвращает JSON-файл со следующими параметрами:

  • id : ID сэмпла
  • creationDate : Дата создания сэмпла в формате ISO 8601 с часовыми поясами
  • lastModified : Дата последнего изменения сэмпла в формате ISO 8601 с часовыми поясами
  • data : Изображение и/или шаблон и/или результат детекции в формате сэмпла

Возвращенный сэмпл автоматически сохраняется на OMNI-сервере (если для параметра anonymousMode установлено значение false) и может использоваться для верификации лиц или поиска людей по базе.

Ошибки входных данных:

  • Отсутствуют входные данные для создания сэмпла:
{
"message": "One of the parameters sampleData or sourceImage is required",
"code": "0xnf5825dh"
}
  • Переданы неверные данные сэмпла:
{
"message": "argument should be a bytes-like object or ASCII string, not 'NoneType'"
}
  • Переданы неверные координаты зрачков:
{
"message": "0x8905a659: Assertion '( transform_m(0, 0) * transform_m(0, 0) + transform_m(0, 1) * transform_m(0, 1) + transform_m(1, 0) * transform_m(1, 0) + transform_m(1, 1) * transform_m(1, 1) ) > 1e-5' failed, error code: 0x8905a659. wrap code: 0x7df96daf."
}

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

mutation{
createSample(image/sampleData: "your image in Base64 format or sample data"){
id
creationDate
lastModified
data
}
}

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

API возвращает следующий результат:
{
"data": {
"createSample": [
{
"id": "3f7352c9-94be-4449-aaa0-b93a3812e1c6",
"creationDate": "2022-04-28T06:23:45.902315+00:00",
"lastModified": "2022-04-28T06:23:46.450993+00:00",
"data": {
"$image": {
"id": "3403c21e-44e1-4ea4-9e57-2d2c0933861e"
},
"objects@common_capturer_uld_fda": [
{
"id": 1,
"age": 23,
"bbox": [
0,
0.21308482869466144,
1,
0.9869169769287109
],
"mask": {
"value": false,
"confidence": 1
},
"class": "face",
"angles": {
"yaw": -0.8611235618591309,
"roll": 1.7437981367111206,
"pitch": -15.951218605041504
},
"gender": "FEMALE",
"emotions": {
"angry": 0.013813868165016174,
"happy": 0.002322095213457942,
"neutral": 0.9834117889404297,
"surprised": 0.00045228638919070363
},
"liveness": {
"value": "FAKE",
"confidence": 0.801980197429657
},
"keypoints": {
"chin": {
"x": 0.4895579020182292,
"y": 0.8763695271809896
},
"nose": {
"x": 0.4884576416015625,
"y": 0.5780504862467448
},
"mouth": {
"x": 0.4904075113932292,
"y": 0.7090469868977864
},
"nose_left": {
"x": 0.3953646511501736,
"y": 0.5805702209472656
},
"left_pupil": {
"x": 0.30088453504774304,
"y": 0.4109149678548177
},
"mouth_left": {
"x": 0.33830030653211807,
"y": 0.6955980936686198
},
"nose_right": {
"x": 0.5848392740885416,
"y": 0.5861359659830729
},
"mouth_right": {
"x": 0.6333636474609375,
"y": 0.6958428955078125
},
"right_pupil": {
"x": 0.6891607666015624,
"y": 0.4170384724934896
},
"left_eye_left": {
"x": 0.21608330620659721,
"y": 0.4157813008626302
},
"left_eye_right": {
"x": 0.3838650173611111,
"y": 0.4230572001139323
},
"right_eye_left": {
"x": 0.6079323323567708,
"y": 0.4287389628092448
},
"left_ear_bottom": {
"x": 0.1043272230360243,
"y": 0.5988115437825521
},
"right_eye_right": {
"x": 0.7724110243055555,
"y": 0.4233682759602865
},
"left_eye_brow_up": {
"x": 0.25802788628472223,
"y": 0.3236322784423828
},
"right_ear_bottom": {
"x": 0.8565327962239583,
"y": 0.607865956624349
},
"right_eye_brow_up": {
"x": 0.7370150417751736,
"y": 0.3286321258544922
},
"left_eye_brow_left": {
"x": 0.1554061550564236,
"y": 0.3466766866048177
},
"left_eye_brow_right": {
"x": 0.3854702419704861,
"y": 0.3430420430501302
},
"right_eye_brow_left": {
"x": 0.6136109754774306,
"y": 0.345932362874349
},
"right_eye_brow_right": {
"x": 0.8359405517578125,
"y": 0.35814239501953127
}
},
"templates": {
"$template10v100": {
"id": "708a5da8-104e-4b83-9f26-ec0329e08b89"
}
},
"$cropImage": {
"id": "3cf0792f-1dde-4e8b-841a-c18330080d21"
},
"quality": -540.9627075195312
}
]
}
}
]
}
}

Верификация лиц

Запрос verify() позволяет сравнить два сэмпла и определить принадлежность двух изображений лиц одному и тому же человеку.

verify(sourceImage: CustomBinaryType = null
sourceSampleData: JSON = null
sourceSampleId: ID = null
targetSampleId: ID!): MatchResult!

sourceImage: CustomBinaryType : Изображение в формате base64

sourceSampleData: JSON : Результат детекции лица, не сохраняемый в базе.

sourceSampleId: ID : ID сэмпла для сравнения с ID целевого сэмпла.

targetSampleId: ID : ID сэмпла для сравнения с исходным изображением, данными исходного сэмпла или ID исходного сэмпла

MatchResult : Результат верификации со следующими параметрами:

  • distance: Параметр показывает дистанцию между сравниваемыми векторами шаблонов. Чем короче дистанция, тем выше степень верификации.

  • faR : False acceptance rate (FAR) Коэффициент ложной идентификации показывает уровень сопротивления системы ошибкам ложной идентификации. Такая ошибка возникает, когда биометрическая система определяет новое лицо как ранее распознанное. Коэффициент измеряется количеством ложных распознаваний, деленным на общее количество попыток распознавания.

  • frR : False rejection rate (FRR). В случае если система не способна распознать ранее обнаруженное лицо, происходит ложное отклонение. Коэффициент ложного отклонения показывает процент попыток распознания с ложным отклонением.

  • score: Параметр показывает уровень верификации от 0 (0%) до 1 (100%)

Ошибки входных данных:

  • Не передан объект сравнения или передана неоднозначно интерпретируемая комбинация:
{
"message": "One of the parameters sourceSampleData or sourceSampleId or sourceImage is required",
"code": "0x963fb254"
}
  • Отсутствует сэмпл по переданному ID:
{
"message": "Sample matching query does not exist."
}
  • Некорректные данные переданного исходного сэмпла:
{
"message": "'objects@common_capturer_uld_fda'"
}

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

{
verify(sourceSampleId:"fa76e8a4-3c90-4007-a72f-94d5fc655c36", targetSampleId:"a2d852e8-aa00-4403-bc5d-f8b94cc183ca")
{
distance
faR
frR
score
}}

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

API возвращает следующий результат:
{
"data": {
"verify": {
"distance": 0,
"faR": 0,
"frR": 1,
"score": 1
}
}
}

Идентификация лиц

Поиск по профилям

Этот запрос позволяет выполнить поиск человека по базе. Функция search() используется для сравнения одного сэмпла со всеми остальными сэмплами в базе.

search(confidenceThreshold: Float = 0
maxNumOfCandidatesReturned: Int = 5
scope: ID = null
sourceImage: CustomBinaryType = null
sourceSampleData: JSON = null
sourceSampleIds: [ID!] = null): [SearchType!]!

confidenceThreshold: Float = 0 : Чтобы исключить совпадения с низкой достоверностью из возвращенного результата, используйте параметр confidenceThreshold (мин. значение: 0, макс. значение: 1; значение по умолчанию: 0)

maxNumOfCandidatesReturned: Int = 5 : Чтобы установить максимальное число возвращенных кандидатов, укажите значение для параметра maxNumOfCandidatesReturned (мин. значение: 1, макс. значение: 100). По умолчанию возвращаются 5 ближайших кандидатов.

scope: ID : По умолчанию поиск человека выполняется по всей базе лиц. Для поиска совпадений по конкретному списку укажите ID списка в поле scope.

sourceImage: CustomBinaryType : Изображение в формате base64

sourceSampleData: JSON : Результат детекции лица, не сохраняемый в базе данных.

sourceSampleIds: [ID!] : ID сэмплов

SearchType! : API возвращает список кандидатов по каждому запрошенному сэмплу в порядке убывания достоверности. Результат поиска включает следующие параметры:

  • template
  • searchResult
    PersonSearchResult
    • sample: SampleOutput! (id: ID!, creationDate: DateTime, lastModified: DateTime, data: JSON!)
    • profile: ProfileOutputData! (id: ID!, info: JSON!, lastModified: DateTime!, creationDate: DateTime!, personId: ID!, mainSample: SampleOutput)
    • matchResult: MatchResult! (distance: Float!, faR: Float!, frR: Float!, score: Float!)

Примечание: исходные данные сравниваются с профилями, созданными на сервере, а не с сэмплами. Таким образом, перед запуском поиска убедитесь, что у вас создан хотя бы 1 профиль.

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

{
search(sourceSampleIds:"fa76e8a4-3c90-4007-a72f-94d5fc655c36"){
template
searchResult{
matchResult{
distance
faR
frR
score}
sample{
id
}
profile{
id
info
}
}
}
}

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

API возвращает следующий результат:
{
"data": {
"search": [
{
"template": "T5JnWuAN4j5MHWRP7tDj7/AOcg9S8AWw4AAQZwJAHeMRw1MUGfkxFTTVUALbWmAHBHJTBKM9LfMgwCUvXlQgAizEAzwP0BvkQDHQfykA4ZDvHrkDFhCvD3Eh73TSD+UQTMDSQBPj4DAtYBEi/wDQMH9A8PMObwQQAFHDAgMOAQHjMB+vEHc2Q/ACH/EHAw+9MPUDA+ImodYPbeKv7Q9/Xw8wD39CPQpQd/wrfwPcZRDSIgkj0PEA8L0NZNoAIdACER8Q/hAQPQAa8UDdovBN6eXBAHUwQOC7DjECPjBQ5FJBE+MNPeAB1OUPEW787jBCAsHQkBCSRXD0MHEP4E0O49IgQ7MBGyBEDyMldtHx4RT0MH9MMReb0g==",
"searchResult": [
{
"matchResult": {
"distance": 0,
"faR": 0,
"frR": 1,
"score": 1
},
"sample": {
"id": "805be807-dd89-4265-9ee7-bbdc19473136"
},
"profile": {
"id": "fd606132-9757-419b-97d6-d8cdd67ed476",
"info": {
"age": 25,
"gender": "MALE",
"main_sample_id": "805be807-dd89-4265-9ee7-bbdc19473136"
}
}
},
{
"matchResult": {
"distance": 9356,
"faR": 0.31920063495635986,
"frR": 0,
"score": 0.0000018477439880371094
},
"sample": {
"id": "c18b3a5a-ccfb-4785-9248-b7ce90052754"
},
"profile": {
"id": "218db30f-b6ff-4a46-a83d-a0701005a12b",
"info": {
"age": 23,
"gender": "FEMALE",
"main_sample_id": "c18b3a5a-ccfb-4785-9248-b7ce90052754"
}
}
}
]
}
]
}
}

Поиск по активностям

Запрос searchInActivities позволяет выполнить поиск человека по активностям.

searchInActivities (
confidenceThreshold: Float = 0
maxNumOfCandidatesReturned: Int = 5
sourceImage: CustomBinaryType = null
sourceSampleData: JSON = null
sourceSampleIds: [ID!] = null
): [ActivitySearchType!]!

confidenceThreshold: Float = 0 : Чтобы исключить совпадения с низкой достоверностью из возвращаемого результата, используйте параметр confidenceThreshold (мин. значение: 0, макс. значение: 1; значение по умолчанию: 0)

maxNumOfCandidatesReturned: Int = 5 : Чтобы установить максимальное число возвращенных кандидатов, укажите значение для параметра maxNumOfCandidatesReturned (мин. значение: 1, макс. значение: 100). По умолчанию возвращаются 5 ближайших кандидатов.

sourceImage: CustomBinaryType : Изображение в формате base64

sourceSampleData: JSON : Результат детекции лица, не сохраняемый в базе данных.

sourceSampleIds: [ID!] : ID сэмплов

ActivitySearchType! : API возвращает список кандидатов в порядке убывания достоверности совпадения. Результат поиска включает следующие параметры:

  • template: String!
  • searchResult: [ActivitySearchResult!]!
    • activity: ActivityOutput ( id: ID! , data: JSON , lastModified: DateTime! , creationDate: DateTime! , bestShotId: ID, cameraId: ID!, locationId: String, profileId: ID, status: ActivityType!, timeStart: String, timeEnd: String )
    • matchResult: MatchResult! ( distance: Float! , faR: Float! , frR: Float! , score: Float! )

Примечание: Поиск осуществляется только по активностям со статусом FINALIZED и FAILED, для которых был вычислен биометрический шаблон.

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

{
searchInActivities(sourceSampleIds: ["fa76e8a4-3c90-4007-a72f-94d5fc655c36"]) {
searchResult {
activity {
id
creationDate
cameraId
bestShotId
}
matchResult {
distance
faR
frR
score
}
}
}
}

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

API возвращает следующий результат:
{
"data": {
"searchInActivities": [
{
"searchResult": [
{
"activity": {
"id": "87c3079b-c93d-49ef-a4d6-f8a4ddb0d1a1",
"creationDate": "2023-02-22T08:53:22.984437+00:00",
"cameraId": "7b896604-5a11-4604-8677-742297b192ab",
"bestShotId": "fabc0b78-054b-4169-96ec-6e39cc6f16c9"
},
"matchResult": {
"distance": 7975,
"faR": 0.026017505675554276,
"frR": 0.004508852958679199,
"score": 0.6593803763389587
}
},
{
"activity": {
"id": "ac7f1848-3270-47dd-9ed4-e119f24aef68",
"creationDate": "2023-02-22T06:29:58.757351+00:00",
"cameraId": "49a1f363-ed9b-428f-bd98-5901dde99618",
"bestShotId": "a47ba56d-5983-48e3-8439-d6b9231c3919"
},
"matchResult": {
"distance": 8044,
"faR": 0.030948175117373466,
"frR": 0.004176795482635498,
"score": 0.653989315032959
}
}
]
}
]
}
}

Ошибки входных данных

  • Не передан объект сравнения или передана неоднозначно интерпретируемая комбинация:
{
"message": "One of the parameters sourceSampleData or sourceSampleId or sourceImage is required",
"code": "0x963fb254"
}
  • Значение параметра confidenceThreshold передается за пределами допустимого диапазона:
{
"message": "Confidence threshold must be between 0 and 1",
"code": "0xf47f116a"
}
  • Значение параметра maxNumOfCandidatesReturned передается за пределами допустимого диапазона:
{
"message": "Max num of candidates must be between 1 and 100",
"code": "0xf8be6762"
}
  • Некорректные данные переданного исходного сэмпла:
{
"message": "'objects@common_capturer_uld_fda'"
}

Профили

Получить список профилей

Запрос profiles() позволяет получить список созданных профилей.

profiles(filter: JSON = null
ids: [ID] = null
limit: Int = null
offset: Int = null
order: [String] = null): ProfilesCollection!

filter: JSON: Вы можете отфильтровать список профилей, указав один или несколько параметров:

  • creation_date: Точная дата создания профиля в формате ISO 8601
  • id: ID профиля из базы данных
  • info: Объект со следующими параметрами:
    • age: Возраст профиля. Например, запрос с параметром info_age:28 вернет список профилей с возрастом 28 лет.
    • gender: Пол профиля. Например, запрос с параметром info_gender: “MALE” вернет список профилей мужского пола.
    • main_sample_id: ID лучшего сэмпла профиля.
    • avatar_id: ID аватара.
  • last_modified: Точная дата последнего изменения профиля в формате ISO 8601
  • link_to_label:
  • person:
  • person_id: ID профиля из базы
  • profile_groups: Список ID групп
  • samples: ID сэмпла
  • workspace: ID воркспейса
  • workspace_id: ID воркспейса

ids: [ID]: Для получения списка конкретных профилей укажите их ID в списке.

limit: Int: Параметр позволяет получить первые n профилей из списка.

offset: Int: Параметр позволяет исключить первые n профилей из списка.

order: [String]: Вы можете отсортировать список по следующим параметрам: creation_date, id, info, last_modified, link_to_label, person, person_id, profile_groups, samples, workspace,workspace_id.

ProfilesCollection!: Результат запроса - список профилей со следующими параметрами:

  • totalCount: Число возвращенных профилей
  • collectionItems: [ProfileOutput!]
    • id: ID профиля
    • lastModified: Дата последнего изменения профиля в формате ISO 8601
    • creationDate: Дата создания профиля в формате ISO 8601
    • info: Информация профиля (примерный возраст, пол, ID аватара, ID лучшего сэмпла)
    • samples: Список сэмплов профиля
    • profileGroups: Список групп профилей
    • mainSample: Лучший сэмпл профиля
    • avatar: Аватар профиля
    • activities: Все активности профиля
    • activitiesCount: Число активностей профиля
    • firstActivityDate: Дата первой активности профиля, зафиксированной системой в формате ISO 8601
    • lastActivityDate: Дата последней активности профиля, зафиксированной системой в формате ISO 8601

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

{
profiles(ids: ["1cf13933-00be-4a6d-8dc3-3ff17f94aef8"]) {
totalCount
collectionItems {
id
avatar
creationDate
firstActivityDate
info
lastActivityDate
lastModified
mainSample {
id
}
profileGroups {
id
}
samples {
id
}
activitiesCount
activities {
id
}
}
}
}

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

API возвращает следующий результат:
{
"data": {
"profiles": {
"totalCount": 1,
"collectionItems": [
{
"id": "1cf13933-00be-4a6d-8dc3-3ff17f94aef8",
"avatar": "dc3e1949-b4e8-4feb-a51c-67740e323e8b",
"creationDate": "2022-07-07T08:59:56.227343+00:00",
"firstActivityDate": "2022-07-07T12:36:51.644000+05:00",
"info": {
"age": 36,
"gender": "MALE",
"avatar_id": "dc3e1949-b4e8-4feb-a51c-67740e323e8b",
"main_sample_id": "3071e862-7116-4ed3-94f1-309b0b5b912f"
},
"lastActivityDate": "2022-07-07T12:37:07.425000+05:00",
"lastModified": "2022-07-07T09:00:15.028365+00:00",
"mainSample": {
"id": "3071e862-7116-4ed3-94f1-309b0b5b912f"
},
"profileGroups": [
{
"id": "97c1a9fa-bfde-460a-9bda-f610060423ca"
}
],
"samples": [
{
"id": "3071e862-7116-4ed3-94f1-309b0b5b912f"
}
],
"activitiesCount": 5,
"activities": [
{
"id": "78f7c795-0f28-42ce-a9d2-818095dd5f84"
},
{
"id": "a4ddc400-8fb8-41ef-aacb-9fc195868368"
},
{
"id": "ea4ba238-4c64-4e07-bed6-d8f29f426e7e"
},
{
"id": "29c8b4f5-11d0-4523-a17f-748ba25d4b97"
},
{
"id": "4a1cad4a-ed81-409e-8a16-38abe9145a77"
}
]
}
]
}
}
}

Создать профиль

Мутация createProfile() используется для создания нового профиля. Созданный профиль автоматически сохраняется на OMNI-сервере.

createProfile(image: CustomBinaryType = null
profileData: ProfileInput = null): ProfileCreateOutput!

image: CustomBinaryType: Для добавления аватара в новый профиль передайте изображение в формате base64 размером до 8Мбайт.

profileData: ProfileInput: Для сохранения дополнительной информации в новом профиле передайте следующие параметры:

  • profileGroupIds: [ID]: Список ID групп, к которым привязан новый профиль
  • info: JSON: Дополнительная информация о профиле (age: Int, gender: "MALE" | "FEMALE")

ProfileCreateOutput!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean: Флаг об успешном завершении мутации
  • profile: ProfileOutput!: Объект нового профиля
  • isCreated: Boolean!: Параметр определяет, были ли создан новый профиль, или фотография прикрепилась к существующему профилю.

Ошибки входных данных:

  • Низкое качество передаваемого изображения:
{
"message": "Low quality photo",
"code": "0x86bd49dh"
}
  • Группы профилей не найдены по переданным ID:
{
"message": "One or several profiles_groups does not exist",
"code": "0x573bkd35"
}

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

mutation{
createProfile {
isCreated
ok
profile {
id
}
}
}

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

API возвращает следующий результат:
{
"data": {
"createProfile": {
"isCreated": true,
"ok": true,
"profile": {
"id": "d5ca09fb-199a-471f-99ca-b9b4954fb45f"
}
}
}
}

Обновить профиль

Мутация updateProfile() используется для обновления информации профиля.

updateProfile(profileData: ProfileInput!
profileId: ID): ProfileUpdateOutput!

profileData: ProfileInput!: Информация профиля для обновления (profileGroupIds: [ID], info: JSON)

profileId: ID: ID профиля

ProfileUpdateOutput!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean: Флаг об успешном завершении мутации
  • profile: ProfileOutput!: Updated profile object

Ошибки входных данных:

  • Профиль не найден по переданному ID
{
"message": "Profile matching query does not exist."
}
  • Группы профилей не найдены по переданным ID
{
"message": "One or several profiles_groups does not exist",
"code": "0x573bkd35"
}

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

mutation{
updateProfile(profileData: {info: {age: 20}}, profileId: "d5ca09fb-199a-471f-99ca-b9b4954fb45f") {
ok
profile {
id
}
}
}

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

API возвращает следующий результат:
{
"data": {
"updateProfile": {
"ok": true,
"profile": {
"id": "d5ca09fb-199a-471f-99ca-b9b4954fb45f"
}
}
}
}

Удалить профиль

Мутация deleteProfiles() используется для удаления профилей.

deleteProfiles(profileIds: [ID!]!): MutationResult!

profileIds: [ID!]: Список ID профилей, которые необходимо удалить

MutationResult!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean: Флаг об успешном завершении мутации

Ошибки входных данных:

  • Пустой список ID профилей, переданных для удаления:
{
"message": "Empty profiles ids list",
"code": "0xd2ae0ef8"
}

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

mutation{
deleteProfiles(profileIds: "d5ca09fb-199a-471f-99ca-b9b4954fb45f") {
ok
}
}

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

API возвращает следующий результат:
{
"data": {
"deleteProfiles": {
"ok": true
}
}
}

Группы

Получить список групп

Запрос profileGroups() позволяет получить список всех групп, хранящихся в базе данных.

profileGroups(filter: JSON = null
ids: [ID] = null
limit: Int = null
offset: Int = null
order: [String] = null): ProfileGroupsCollection!

filter: JSON: Вы можете отфильтровать список групп по одному или нескольким параметрам:

  • area_type:
  • attention_areas:
  • camera_location:
  • cameras:
  • creation_date: Точная дата создания группы в формате ISO 8601
  • id: ID группы из базы данных
  • info: В формате JSON, полностью аналогичен параметру info объекта группы
  • last_modified: Точная дата последнего изменения группы в формате ISO 8601
  • link_to_profile:
  • profiles: Список ID профилей
  • title: Название группы
  • type:
  • workspace: ID воркспейса
  • workspace_id: ID воркспейса

ids: [ID]: Для получения списка конкретных групп укажите их ID в списке.

limit: Int: Параметр позволяет получить первые n профилей из списка.

offset: Int: Параметр позволяет убрать первыеn профилей из списка.

order: [String]:

ProfileGroupsCollection!: Результат мутации - список групп со следующими параметрами:


  • totalCount: Число возвращенных групп
  • collectionItems: [ProfileGroupOutput!]!:
    • id: ID группы
    • title: Название группы
    • info: Дополнительная информация о группе в JSON-формате
    • lastModified: Дата последнего изменения группы в формате ISO 8601
    • creationDate: Дата создания группы в формате ISO 8601
    • profileIds: Список ID профилей, добавленных в группу

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

{
profileGroups(ids: ["97c1a9fa-bfde-460a-9bda-f610060423ca"]) {
totalCount
collectionItems {
id
creationDate
info
lastModified
profileIds
title
}
}
}

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

API возвращает следующий результат:
{
"data": {
"profileGroups": {
"totalCount": 1,
"collectionItems": [
{
"id": "97c1a9fa-bfde-460a-9bda-f610060423ca",
"creationDate": "2022-07-07T07:21:06.428216+00:00",
"info": {
"color": "red.600"
},
"lastModified": "2022-07-07T07:21:06.428205+00:00",
"profileIds": [
"e4975119-cac7-4ced-ae3f-779bb1093c89",
"1cf13933-00be-4a6d-8dc3-3ff17f94aef8",
"b4a16647-1336-4ed8-a440-e4e8896e1de3"
],
"title": "My persons"
}
]
}
}
}

Создать группу

Мутация createProfileGroup() позволяет создать группу. Созданная группа автоматически сохраняется на OMNI Platform-сервере.

createProfileGroup(profileGroupData: ProfileGroupInput!): ProfileGroupModifyOutput!

profileGroupData: ProfileGroupInput!: JSON с данными для создания группы:

  • title: String!: Название новой группы
  • info: JSON = null: Дополнительная информация о группе

ProfileGroupInput!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean: Флаг об успешном завершении мутации
  • profileGroup: ProfileGroupOutput: Объект новой группы

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

mutation{
createProfileGroup(profileGroupData: {title: "My new group"}) {
ok
profileGroup {
creationDate
id
info
lastModified
profileIds
title
}
}
}

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

API возвращает следующий результат:
{
"data": {
"createProfileGroup": {
"ok": true,
"profileGroup": {
"creationDate": "2022-07-08T07:44:10.766783+00:00",
"id": "d77c80eb-fffb-4812-a63c-cd8007270ef3",
"info": {},
"lastModified": "2022-07-08T07:44:10.766767+00:00",
"profileIds": [],
"title": "My new group"
}
}
}
}

Удалить группу

Мутация deleteProfileGroup() позволяет удалить список групп.

deleteProfileGroup(groupIds: [ID!]!): MutationResult!

groupIds: [ID!]!: Список ID групп, которые необходимо удалить

MutationResult!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean: Флаг об успешном завершении мутации

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

mutation{
deleteProfileGroup(groupIds: ["d77c80eb-fffb-4812-a63c-cd8007270ef3"]) {
ok
}
}

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

API возвращает следующий результат:
{
"data": {
"deleteProfileGroup": {
"ok": true
}
}
}

Обновить группу

Мутация updateProfileGroupInfo() используется для обновления информации группы.

updateProfileGroupInfo(profileGroupData: ProfileGroupModifyInput!
profileGroupId: ID!): ProfileGroupModifyOutput!

profileGroupData: ProfileGroupModifyInput!: JSON с информацией для обновления:

  • title: Название группы
  • info: Дополнительная информация о группе

profileGroupId: ID!: ID группы

ProfileGroupModifyOutput!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean: Флаг об успешном завершении мутации
  • profileGroup: ProfileGroupOutput: Обновленный объект группы

Ошибки входных данных:

  • Группа не найдена по переданному ID:
{
"message": "Label matching query does not exist."
}

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

mutation{
updateProfileGroupInfo(profileGroupData: {title: "New group's name"}, profileGroupId: "800f0b65-7dbe-42b2-8f66-89af95a734e7") {
ok
profileGroup {
id
title
}
}
}

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

API возвращает следующий результат:
{
"data": {
"updateProfileGroupInfo": {
"ok": true,
"profileGroup": {
"id": "800f0b65-7dbe-42b2-8f66-89af95a734e7",
"title": "New group's name"
}
}
}
}

Добавить профили в группы

Мутация addProfilesToGroups() позволяет добавить профили в одну или несколько групп.

addProfilesToGroups(groupIds: [ID!]!
profilesIds: [ID!]!): ProfilesUpdateOutput!

groupIds: [ID!]!: Список ID групп

profilesIds: [ID!]!: Список ID профилей

ProfilesUpdateOutput!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean: Флаг об успешном завершении мутации
  • profiles: [ProfileOutput!]!: Список обновленных профилей

Ошибки входных данных:

  • Профиль не найден по переданному ID:
{
"message": "Profile matching query does not exist."
}
  • Группы не найдены по переданным ID:
{
"message": "One or several profiles_groups does not exist",
"code": "0x573bkd35"
}

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

mutation{
addProfilesToGroups(
groupIds: ["5b53aa69-d515-4fd3-81bf-c3d8696c3ab8", "800f0b65-7dbe-42b2-8f66-89af95a734e7"],
profilesIds: ["1cf13933-00be-4a6d-8dc3-3ff17f94aef8", "292a2f47-8bfd-4782-8fdf-c8b8189e300e", "3f4c1579-4e5e-4ef4-b9e1-a19808c4d931"]
) {
ok
profiles {
id
profileGroups {
id
}
}
}
}

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

API возвращает следующий результат:
{
"data": {
"addProfilesToGroups": {
"ok": true,
"profiles": [
{
"id": "1cf13933-00be-4a6d-8dc3-3ff17f94aef8",
"profileGroups": [
{
"id": "97c1a9fa-bfde-460a-9bda-f610060423ca"
},
{
"id": "5b53aa69-d515-4fd3-81bf-c3d8696c3ab8"
},
{
"id": "800f0b65-7dbe-42b2-8f66-89af95a734e7"
}
]
},
{
"id": "292a2f47-8bfd-4782-8fdf-c8b8189e300e",
"profileGroups": [
{
"id": "5b53aa69-d515-4fd3-81bf-c3d8696c3ab8"
},
{
"id": "800f0b65-7dbe-42b2-8f66-89af95a734e7"
}
]
},
{
"id": "3f4c1579-4e5e-4ef4-b9e1-a19808c4d931",
"profileGroups": [
{
"id": "edbb2c49-bacc-4b43-aac8-e06fd3da35eb"
},
{
"id": "5b53aa69-d515-4fd3-81bf-c3d8696c3ab8"
},
{
"id": "800f0b65-7dbe-42b2-8f66-89af95a734e7"
}
]
}
]
}
}
}

Удалить профили из групп

Мутация removeProfilesFromGroups() используется для удаления выбранных профилей из одной или нескольких групп.

removeProfilesFromGroups(groupIds: [ID!]!
profilesIds: [ID!]!): ProfilesUpdateOutput!

groupIds: [ID!]!: Список ID групп

profilesIds: [ID!]!: Список ID профилей

ProfilesUpdateOutput!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean: Флаг об успешном завершении мутации
  • profiles: [ProfileOutput!]!: Список обновленных профилей

Ошибки входных данных:

  • Профиль не найден по переданному ID:
{
"message": "Profile matching query does not exist."
}
  • Группы не найдены по переданным ID:
{
"message": "One or several profiles_groups does not exist",
"code": "0x573bkd35"
}

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

mutation{
removeProfilesFromGroups(
groupIds: ["5b53aa69-d515-4fd3-81bf-c3d8696c3ab8", "800f0b65-7dbe-42b2-8f66-89af95a734e7"],
profilesIds: ["1cf13933-00be-4a6d-8dc3-3ff17f94aef8", "292a2f47-8bfd-4782-8fdf-c8b8189e300e", "3f4c1579-4e5e-4ef4-b9e1-a19808c4d931"]
) {
ok
profiles {
id
profileGroups {
id
}
}
}
}

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

API возвращает следующий результат:
{
"data": {
"removeProfilesFromGroups": {
"ok": true,
"profiles": [
{
"id": "1cf13933-00be-4a6d-8dc3-3ff17f94aef8",
"profileGroups": [
{
"id": "97c1a9fa-bfde-460a-9bda-f610060423ca"
}
]
},
{
"id": "292a2f47-8bfd-4782-8fdf-c8b8189e300e",
"profileGroups": []
},
{
"id": "3f4c1579-4e5e-4ef4-b9e1-a19808c4d931",
"profileGroups": [
{
"id": "edbb2c49-bacc-4b43-aac8-e06fd3da35eb"
}
]
}
]
}
}
}

Эндпойнты

Получить эндпойнты

Запрос endpoints() позволяет получить список эндпойнтов, на которые направляются оповещения.

endpoints(filter: JSON = null
ids: [ID] = null
limit: Int = null
offset: Int = null
order: [String] = null
withArchived: WithArchived = null): EndpointCollection!

filter: JSON: Вы можете отфильтровать список эндпойнтов по одному или нескольким параметрам:

  • creation_date: Точная дата создания эндпойнта в формате ISO 8601
  • id: ID эндпойнта из базы данных
  • is_active:
  • last_modified: Точная дата последнего изменения эндпойнта в формате ISO 8601
  • meta: JSON-файл с данными по нахождению эндпойнта
  • triggers: ID триггера, который запускает оповещения
  • type: Параметр включает следующие типы эндпойнтов (WI = веб-интерфейс, EM = Email, WH = веб-хук)
  • workspace: ID воркспейса
  • workspace_id: ID воркспейса

ids: [ID]: Для получения списка конкретных эндпойнтов укажите их ID в списке.

limit: Int: Параметр позволяет получить первые n профилей из списка.

offset: Int: Параметр позволяет удалить первые n профилей из списка.

order: [String]:

withArchived: WithArchived: Для получения списка всех эндпойнтов, включая архивированные, укажите значение all. Для получения только архивированных эндпойнтов укажите значение archived.

EndpointCollection!: Результат запроса - список эндпойнтов со следующими параметрами:

  • totalCount: Число возвращенных эндпойнтов
  • profiles: [EndpointOutput!]!:
    • id: ID!: ID эндпойнта
    • type: EndpointType!: Тип эндпойнта может иметь следующие значения: Email, Webhook или WebInterface
    • meta: JSONString!: Мета-информация для нахождения эндпойнта
    • lastModified: DateTime!: Дата последнего изменения эндпойнта в формате ISO 8601
    • creationDate: DateTime!: Дата создания эндпойнта в формате ISO 8601
    • defaultAlias: DefaultAlias:
      • OWNER_EMAIL
      • WEB_INTERFACE
    • archived: Boolean!: Атрибут указывает на то, что эндпойнт заархивирован.

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

{
endpoints(ids: ["6fd67f81-a195-442b-a991-1a0eca6bbb69"]) {
totalCount
collectionItems {
archived
creationDate
id
defaultAlias
lastModified
meta
type
}
}
}

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

API возвращает следующий результат:
{
"data": {
"endpoints": {
"totalCount": 1,
"collectionItems": [
{
"archived": false,
"creationDate": "2022-07-07T07:21:06.421413+00:00",
"id": "6fd67f81-a195-442b-a991-1a0eca6bbb69",
"defaultAlias": "OWNER_EMAIL",
"lastModified": "2022-07-07T07:21:06.421425+00:00",
"meta": "{\"target_email\": \"aa@aa.ru\", \"default_alias\": \"owner_email\"}",
"type": "Email"
}
]
}
}
}

Создать эндпойнт типа email

Мутация createEmailEndpoint() позволяет создать эндпойнт типа Email.

createEmailEndpoint(endpointData: EmailEndpointInput!): EndpointManageOutput!

endpointData: EmailEndpointInput!: JSON с информацией по созданию эндпойнта:

  • targetEmail: String!: Email, куда будут отправляться оповещения.

EndpointManageOutput!: Результат мутации - JSON со следующими параметрами:

  • ok: Boolean!: Атрибут успешного завершения мутации
  • endpoint: EndpointOutput!: Объект нового эндпойнта

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

mutation {
createEmailEndpoint(endpointData: {targetEmail: "test@test.com"}) {
ok
endpoint {
id
archived
creationDate
defaultAlias
lastModified
meta
type
}
}
}

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

API возвращает следующий результат:
{
"data": {
"createEmailEndpoint": {
"ok": true,
"endpoint": {
"id": "2eff291d-8c8c-4325-8953-5a70b31bc63e",
"archived": false,
"creationDate": "2022-07-10T12:27:22.568988+00:00",
"defaultAlias": null,
"lastModified": "2022-07-10T12:27:22.569003+00:00",
"meta": "{\"target_email\": \"test@test.com\"}",
"type": "EMAIL"
}
}
}
}

Создать эндпойнт типа webhook

Мутация createWebhookEndpoint() позволяет создать эндпойнт типа Webhook.

createWebhookEndpoint(endpointData: WebhookEndpointInput!): EndpointManageOutput!

endpointData: WebhookEndpointInput!: JSON с информацией для создания эндпойнта:

  • url: String!: URL, куда будут отправляться запросы
  • requestMethod: String!: Метод запроса

EndpointManageOutput!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean!: Атрибут успешного завершения мутации
  • endpoint: EndpointOutput!: Объект нового эндпойнта

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

mutation {
createWebhookEndpoint(endpointData: {url: "https://endpoint_test.requestcatcher.com/test /", requestMethod: "POST"}) {
ok
endpoint {
archived
creationDate
defaultAlias
id
lastModified
meta
type
}
}
}

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

API возвращает следующий результат:
{
"data": {
"createWebhookEndpoint": {
"ok": true,
"endpoint": {
"archived": false,
"creationDate": "2022-07-10T12:42:34.957171+00:00",
"defaultAlias": null,
"id": "afd7c121-3140-4a8c-b0ee-3717581eb76d",
"lastModified": "2022-07-10T12:42:34.957188+00:00",
"meta": "{\"url\": \"https://endpoint_test.requestcatcher.com/test /\", \"method\": \"POST\"}",
"type": "WEBHOOK"
}
}
}
}

Обновить эндпойнт

Мутация updateEndpoint() позволяет обновить данные эндпойнта.

updateEndpoint(endpointId: ID!
endpointInfo: JSON): EndpointManageOutput!

endpointId: ID!: ID эндпойнта

endpointInfo: JSON: JSON-объект с параметрами для обновления. Эти параметры аналогичны параметрам из meta: JSON

EndpointManageOutput!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean!: Атрибут успешного завершения мутации
  • endpoint: EndpointOutput!: Объект обновленного эндпойнта

Ошибки входных данных:

  • Эндпойнт не найден по переданному ID:
{
"message": "Endpoint matching query does not exist."
}

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

mutation {
updateEndpoint(endpointId: "6fd67f81-a195-442b-a991-1a0eca6bbb69", endpointInfo: {target_email: "new-email@test.com"}) {
ok
endpoint {
id
meta
}
}
}

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

API возвращает следующий результат:
{
"data": {
"updateEndpoint": {
"ok": true,
"endpoint": {
"id": "6fd67f81-a195-442b-a991-1a0eca6bbb69",
"meta": "{\"target_email\": \"new-email@test.com\", \"default_alias\": \"owner_email\"}"
}
}
}
}

Удалить эндпойнты

Мутация deleteEndpoint() позволяет удалить список эндпойнтов.

deleteEndpoint(endpointIds: [String!]!): MutationResult!

endpointIds: [String!]!: Список ID эндпойнтов

MutationResult!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean!: Атрибут успешного завершения мутации

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

mutation {
deleteEndpoint(endpointIds: ["2eff291d-8c8c-4325-8953-5a70b31bc63e", "29bcfb3a-3a26-4544-9def-d5d44bbd3be4"]) {
ok
}
}

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

API возвращает следующий результат:
{
"data": {
"deleteEndpoint": {
"ok": true
}
}
}

Триггеры

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

Запрос triggers позволяет получить список триггеров для создания оповещений. Триггеры связаны с эндпойнтами, на которые будут отправляться оповещения.

triggers(filter: JSON = null
ids: [ID] = null
limit: Int = null
offset: Int = null
order: [String] = null
targetId: ID = null
withArchived: WithArchived = null): TriggerCollection!

filter: JSON: Вы можете отфильтровать список триггеров, указав один или несколько параметров:

  • creation_date: Точная дата создания триггера в формате ISO 8601
  • endpoints: ID связанного эндпойнта
  • id: ID триггера из базы данных
  • is_active:
  • last_modified: Точная дата последнего изменения триггера в формате ISO 8601
  • meta:
  • workspace: ID воркспейса
  • workspace_id: ID воркспейса

ids: [ID]: Для получения списка конкретных триггеров укажите их ID в списке.

limit: Int: Параметр позволяет получить первые n триггеров из списка.

offset: Int: Параметр позволяет удалить первые n триггеров из списка.

order: [String]: Вы можете отсортировать список, указав значения для следующих параметров:creation_date, endpoints, id, is_active, last_modified, meta, workspace, workspace_id

targetId: ID: ID группы, к которой привязан триггер

withArchived: WithArchived: Для получения списка всех триггеров, включая заархивированные триггеры, укажите значение all. Для получения списка только заархивированных триггеров укажите значение archived.

TriggerCollection!: Результат запроса - список триггеров со следующими параметрами:

  • totalCount: Int: Число возвращенных триггеров
  • collectionItems: [TriggerType!]!:
    • id: ID!: ID триггера
    • creationDate: DateTime!: Дата создания триггера в формате ISO 8601
    • lastModified: DateTime!: Дата последнего изменения триггера в формате ISO 8601
    • meta: Meta!: Мета-информация триггера
    • endpoints: [EndpointOutput!]!: Список эндпойнтов, связанных с триггером
    • archived: Boolean!: Атрибут об архивации триггера

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

{
triggers(ids: ["3e57a95e-028c-4d27-9419-a9c4bfd6f3fb"]) {
totalCount
collectionItems {
id
creationDate
lastModified
meta {
notificationParams
conditionLanguage {
condition
variables {
name
target {
type
uuid
}
type
}
}
}
endpoints {
id
}
archived
}
}
}

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

API возвращает следующий результат:
{
"data": {
"triggers": {
"totalCount": 1,
"collectionItems": [
{
"id": "3e57a95e-028c-4d27-9419-a9c4bfd6f3fb",
"creationDate": "2022-07-07T08:38:22.982190+00:00",
"lastModified": "2022-07-08T05:03:48.961423+00:00",
"meta": {
"notificationParams": "{\"lifetime\": 5}",
"conditionLanguage": {
"condition": null,
"variables": [
{
"name": "0_v",
"target": [
{
"type": "Label",
"uuid": "edbb2c49-bacc-4b43-aac8-e06fd3da35eb"
}
],
"type": "presence"
}
]
}
},
"endpoints": [
{
"id": "db38ec53-c09d-45f2-bfed-5877c9bd9016"
}
],
"archived": false
}
]
}
}
}

Создать триггер для группы

Мутация createProfileGroupTrigger позволяет создать триггер для группы. При каждом обнаружении камерой персоны из этой группы система будет создавать оповещение.

createProfileGroupTrigger(endpointAliases: [DefaultAlias!] = null
endpointIds: [ID!] = null
endpointUrl: String = null
profileGroupId: ID!): TriggerManageOutput!

endpointAliases: [DefaultAlias!]: Вы можете передать значения OWNER_EMAIL или WEB_INTERFACE. В этом случае эндпойнт с аналогичным значением для параметра defaultAlias будет привязан к триггеру.

endpointIds: [ID!]: Вы можете передать список ID эндпойнтов, привязанных к триггеру.

endpointUrl: String: Вы можете передать URL в ваш вебхук. Это создаст новый эндпойнт для отправления оповещений на ваш URL адрес.

profileGroupId: ID!: ID группы для создания триггера.

TriggerManageOutput!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean!: Атрибут успешного завершения мутации
  • trigger: TriggerType!: Объект нового триггера

Ошибки входных данных:

  • Группа не найдена по переданному ID:
{
"message": "Label matching query does not exist."
}
  • Эндпойнт не найден по переданному ID:
{
"message": "Endpoint does not exist."
}

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

mutation{
createProfileGroupTrigger(profileGroupId: "800f0b65-7dbe-42b2-8f66-89af95a734e7", endpointIds: ["afd7c121-3140-4a8c-b0ee-3717581eb76d"]) {
trigger {
endpoints {
id
}
id
}
}
}

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

API возвращает следующий результат:
{
"data": {
"createProfileGroupTrigger": {
"trigger": {
"endpoints": [
{
"id": "afd7c121-3140-4a8c-b0ee-3717581eb76d"
}
],
"id": "9675aede-3ee8-495b-ac8b-e284a07db99e"
}
}
}
}

Обновить триггер

Мутация updateTrigger позволяет обновить эндпойнты, привязанные к триггеру. Список привязанных эндпойнтов заменяется новым списком.

updateTrigger(endpointAliases: [DefaultAlias!] = null
endpointIds: [ID!] = null
triggerId: ID!): TriggerManageOutput!

endpointAliases: [DefaultAlias!]: Вы можете передать значения OWNER_EMAIL или WEB_INTERFACE. В этом случае один из эндпойнтов с аналогичным значением в параметре defaultAlias будет привязан к триггеру.

endpointIds: [ID!]: Вы можете передать список ID эндпойнтов, привязанных к триггеру.

triggerId: ID!: ID триггера

TriggerManageOutput!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean!: Атрибут успешного завершения мутации
  • trigger: TriggerType!: Объект обновленного триггера

Ошибки входных данных:

  • Триггер не найден по переданному ID:
{
"message": "Trigger matching query does not exist."
}
  • Эндпойнт не найден по переданному ID:
{
"message": "Endpoint does not exist."
}

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

mutation{
updateTrigger(
triggerId: "64e0a7ec-0df4-4734-a460-601fa1b65a1f",
endpointIds: ["6e5a6d3b-8247-488e-95d7-57a306b294ed"],
endpointAliases: OWNER_EMAIL) {
ok
trigger {
id
endpoints {
id
defaultAlias
}
}
}
}

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

API возвращает следующий результат:
{
"data": {
"updateTrigger": {
"ok": true,
"trigger": {
"id": "64e0a7ec-0df4-4734-a460-601fa1b65a1f",
"endpoints": [
{
"id": "6e5a6d3b-8247-488e-95d7-57a306b294ed",
"defaultAlias": null
},
{
"id": "6fd67f81-a195-442b-a991-1a0eca6bbb69",
"defaultAlias": "OWNER_EMAIL"
}
]
}
}
}
}

Мутация linkEndpoint позволяет привязать эндпойнт к триггеру. Необходимо добавить эндпойнт в список эндпойнтов, привязанных к триггеру.

linkEndpoint(endpointAliases: [DefaultAlias!] = null
endpointIds: ID! = null
triggerId: ID!): MutationResult!

endpointAliases: [DefaultAlias!]: Можно передать значения OWNER_EMAIL или WEB_INTERFACE. В этом случае один из эндпойнтов с аналогичным значением для параметраdefaultAlias будет привязан к триггеру.

endpointIds: ID!: ID эндпойнта, который будет привязан к триггеру.

triggerId: ID!: ID триггера

MutationResult!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean!: Атрибут успешного завершения мутации

Ошибки входных данных:

  • Не передан ID эндпойнта для привязки к триггеру:
{
"message": "Unknown exception code for 'bad_input_data' type",
"code": "No id or alias provided"
}
  • Не найден эндпойнт по переданному ID:
{
"message": "Endpoint matching query does not exist."
}
  • Не найден триггер по переданному ID:
{
"message": "Trigger matching query does not exist."
}

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

mutation{
linkEndpoint(triggerId: "64e0a7ec-0df4-4734-a460-601fa1b65a1f", endpointAlias: WEB_INTERFACE) {
ok
}
}

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

API возвращает следующий результат:
{
"data": {
"linkEndpoint": {
"ok": true
}
}
}

Мутация unlinkEndpoint позволяет отвязать эндпойнт от триггера. Эндпойнт будет удален из списка эндпойнтов, привязанных к триггеру.

unlinkEndpoint(endpointAliases: [DefaultAlias!] = null
endpointIds: ID! = null
triggerId: ID!): MutationResult!

endpointAliases: [DefaultAlias!]: Вы можете передать значения OWNER_EMAIL или WEB_INTERFACE. В этом случае один из эндпойнтов с аналогичным значением параметра defaultAlias будет удален из списка эндпойнтов, привязанных к этому триггеру.

endpointIds: ID!: Вы можете передать ID эндпойнта, который необходимо удалить из списка эндпойнтов, привязанных к этому триггеру.

triggerId: ID!: ID триггера

MutationResult!: Результат мутации - JSON-файл со следующими параметрами::

  • ok: Boolean!: Атрибут успешного завершения мутации

Ошибки входных данных:

  • ID эндпойнта, который необходимо отвязать от триггера, не передан:
{
"message": "Unknown exception code for 'bad_input_data' type",
"code": "No id or alias provided"
}
  • Эндпойнт не найден по переданному ID:
{
"message": "Endpoint matching query does not exist."
}
  • Триггер не найден по переданному ID:
{
"message": "Trigger matching query does not exist."
}

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

mutation{
unlinkEndpoint(triggerId: "64e0a7ec-0df4-4734-a460-601fa1b65a1f", endpointAlias: WEB_INTERFACE) {
ok
}
}

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

API возвращает следующий результат:
{
"data": {
"unlinkEndpoint": {
"ok": true
}
}
}

Удалить триггер

Мутация deleteTrigger позволяет удалить триггер.

deleteTrigger(triggerId: ID!): MutationResult!

triggerId: ID!: ID триггера

MutationResult!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean!: Атрибут успешного завершения мутации.

Ошибки входных данных:

  • Триггер не найден по переданному ID:
{
"message": "Trigger matching query does not exist."
}

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

mutation{
deleteTrigger(triggerId: "64e0a7ec-0df4-4734-a460-601fa1b65a1f") {
ok
}
}

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

API возвращает следующий результат:
{
"data": {
"deleteTrigger": {
"ok": true
}
}
}

Оповещения

Получить список оповещений

Запрос notifications позволяет получить список оповещений.

notifications(filters: NotificationFilter
order: NotificationOrdering
pagination: OffsetPaginationInput): NotificationOutputCountList!

filters: NotificationFilter: Можно настроить получение списка конкретных оповещений

  • id: Фильтрация по ID оповещений:
    • exact: ID: Получить точный объект оповещения по ID оповещения.
    • iExact: ID: Получить точный объект оповещения по ID оповещения. Без учета регистра.
    • contains: String: Получить объекты оповещений, в которых значение является частью ID оповещения.
    • iContains: String: Получить объекты оповещений, в которых значение является частью ID оповещения. Без учета регистра.
    • inList: [ID!]: Получить точные объекты оповещений по списку ID оповещений.
    • gt: ID: Получить объекты оповещений с ID больше(>) переданных ID. Используется сравнение строк.
    • gte: ID: Получить объекты оповещений с ID больше или равным (>=) переданным ID. Используется сравнение строк.
    • lt: ID: Получить объекты оповещений с ID меньше (<) переданных ID. Используется сравнение строк.
    • lte: ID: Получить объекты оповещений с ID меньше или равным(<=) переданным ID. Используется сравнение строк.
    • startsWith: String: Получить объекты оповещений, чьи ID начинаются с переданного значения.
    • iStartsWith: String: Получить объекты оповещений, чьи ID начинаются с переданного значения. Без учета регистра.
    • endsWith: String: Получить объекты оповещений, чьи ID заканчиваются переданным значением.
    • iEndsWith: String: Получить объекты оповещений, чьи ID заканчиваются переданным значением. Без учета регистра.
    • range: [ID!]: Получить объекты оповещений, чьи ID находятся в диапазоне переданных ID. Используется сравнение строк.
    • isNull: Boolean: Получить объекты оповещений, чьи ID равны(true) или не равны (false) нулю null.
    • regex: String: Получить объекты оповещений, чьи ID соответствуют переданному регулярному выражению.
    • iRegex: String: Получить объекты оповещений, чьи ID соответствуют переданному регулярному выражению. Без учета регистра.
  • creationDate: DatetimeFilterLookupCustom: Фильтрация по дате создания оповещения. Параметры аналогичны параметрам для фильтрации по ID.
  • lastModified: DatetimeFilterLookupCustom: Фильтрация по дате последнего изменения оповещения. Параметры аналогичны параметрам для фильтрации по ID.
  • isViewed: Boolean: Фильтрация просмотренных (true) и непросмотренных (false) оповещений.
  • isActive: Boolean: Фильтрация активных (true) и неактивных (false) оповещений.
  • endpointId: UUID: Фильтрация оповещений по ID эндпойнта, на который отправляются оповещения.
  • isSent: Boolean: Фильтрация оповещений по оповещениям внутри системы (true) и оповещениям, направленным на внешние эндпойнты (false).
  • triggerId: ID: Фильтрация оповещений по ID триггера.
  • profileId: ID: Фильтрация оповещений по ID профиля.
  • type: NotificationType: Фильтрация оповещений по типу.
  • profileGroupTitle: String: Фильтрация оповещений по названию группы.

order: NotificationOrdering: Вы можете настроить сортировку списка оповещений:

  • id: Ordering: Сортировка по ID. Используется сравнение строк. (ASC: Сортировка по возрастанию, DESC: Сортировка по убыванию)
  • creationDate: Ordering: Сортировка по дате создания оповещения.
  • lastModified: Ordering: Сортировка по дате последнего изменения оповещения.

pagination: OffsetPaginationInput:

  • limit: Int!: Этот параметр позволяет получить первые n оповещений из списка.
  • offset: Int!: Этот параметр позволяет удалить первые n оповещений из списка.

NotificationOutputCountList!: Результат запроса - список оповещений со следующими параметрами:

  • totalCount: Int!: Общее число оповещений.
  • collectionItems: [NotificationOutput!]!:
    • id: ID!: ID оповещения.
    • isActive: Boolean!: Атрибут о том, что оповещение активно.
    • isViewed: Boolean!: Атрибут о том, что оповещение просмотрено.
    • lastModified: DateTime: Дата последнего изменения оповещения в формате ISO 8601.
    • activityId: ID: ID активности, вызвавшей оповещение.
    • avatarId: ID: ID аватара профиля.
    • cameraId: ID: ID камеры, обнаружившей активность.
    • cameraTitle: String: Название камеры
    • creationDate: DateTime!: Дата создания оповещения в формате ISO 8601.
    • currentCount: Int: Число людей в поле зрения камеры
    • description: String: Описание профиля
    • endpointStatuses: [EndpointStatusOutput!]: Список эндпойнтов со статусами:
      • endpoint: EndpointOutput!: Объект эндпойнта.
      • status: String!: Статус передачи.
    • limit: Int: Максимальное число персон.
    • name: String: Имя профиля.
    • profileGroupColor: String: Цвет группы, привязанной к триггеру.
    • profileGroupId: ID: ID группы, привязанной к триггеру.
    • profileGroupTitle: String: Название группы, привязанной к триггеру.
    • profileId: ID: ID профиля.
    • realtimeBodyPhotoId: String: ID изображения человека, обнаруженного камерой (Отсутствует в анонимном режиме).
    • realtimeFacePhotoId: String: ID изображения лица человека, обнаруженного камерой (Отсутствует в анонимном режиме).
    • triggerId: ID: ID триггера, вызвавшего оповещение.
    • type: String!: Тип оповещения.

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

{
notifications(filters: {
id: {
exact: "ed1a55af-6daf-4368-ac68-0defdff5159c"
}
}) {
totalCount
collectionItems {
profileGroupColor
activityId
avatarId
cameraId
cameraTitle
creationDate
currentCount
description
id
endpointStatuses {
status
endpoint {
id
}
}
isActive
isViewed
lastModified
limit
name
profileGroupId
profileGroupTitle
profileId
realtimeBodyPhotoId
realtimeFacePhotoId
triggerId
type
}
}
}

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

API возвращает следующий результат:
{
"data": {
"notifications": {
"totalCount": 1,
"collectionItems": [
{
"profileGroupColor": "red.600",
"activityId": "f3bf0ac7-5849-45d7-85e0-12de925633da",
"avatarId": "4312809b-99b2-47a7-beb9-b60b87c07594",
"cameraId": "3c818dc4-352c-47a7-b32b-465fbd4a9665",
"cameraTitle": "My Nuitrack Agent",
"creationDate": "2022-07-07T13:10:53.619145+00:00",
"currentCount": null,
"description": "gap\n",
"id": "ed1a55af-6daf-4368-ac68-0defdff5159c",
"endpointStatuses": [
{
"status": "success",
"endpoint": {
"id": "db38ec53-c09d-45f2-bfed-5877c9bd9016"
}
}
],
"isActive": false,
"isViewed": true,
"lastModified": "2022-07-07T13:11:12.264337+00:00",
"limit": null,
"name": null,
"profileGroupId": "97c1a9fa-bfde-460a-9bda-f610060423ca",
"profileGroupTitle": "My persons",
"profileId": "b4a16647-1336-4ed8-a440-e4e8896e1de3",
"realtimeBodyPhotoId": "339a4020-a9af-49e8-83d4-3fc34ef794e5",
"realtimeFacePhotoId": null,
"triggerId": "66b3eb1a-de88-469e-83c9-697785a0a4c2",
"type": "presence"
}
]
}
}
}

Просмотреть оповещение

Мутация viewingNotifications отмечает одно или несколько оповещений как просмотренные.

viewingNotifications(notificationIds: [String!]!): MutationResult!

notificationIds: [String!]!: Список ID оповещений, отмеченных как просмотренные.

MutationResult:Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean!: Атрибут успешного завершения мутации.

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

mutation{
viewingNotifications(notificationIds: ["5a1a1bed-5bc0-4e8e-8154-e56c5ef5ea87"]) {
ok
}
}

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

API возвращает следующий результат:
{
"data": {
"viewingNotifications": {
"ok": true
}
}
}

Просмотреть все оповещения

Мутация markAllNotificationsAsViewed отмечает все оповещения как просмотренные.

markAllNotificationsAsViewed: MutationResult!

MutationResult: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean!: Атрибут успешного завершения мутации.

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

mutation{
markAllNotificationsAsViewed {
ok
}
}

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

API возвращает следующий результат:
{
"data": {
"markAllNotificationsAsViewed": {
"ok": true
}
}
}

Активности

Получить список активностей

Запрос activities позволяет получить список активностей, обнаруженных камерой.

notifications(filters: ActivityFilter order: ActivityOrdering pagination: OffsetPaginationInput): ActivityOutputCountList!

filters: ActivityFilter: Для получения только конкретных активностей можно настроить фильтрацию

  • id: Фильрация по ID активности:

    • exact: ID: Получить точный объект активности по значению ID активности.

    • iExact: ID: Получить точный объект активности по значению ID активности. Без учета регистра.

    • contains: String: Получить объекты активностей, в которых значение является частью ID активности.

    • iContains: String: Получить объекты активностей, в которых значение является частью ID активности. Без учета регистра.

    • inList: [ID!]: Получить точные объекты активностей по списку ID активностей.

    • gt: ID: Получить объекты активностей с ID больше(>) переданных ID. Используется сравнение строк.

    • gte: ID: Получить объекты активностей с ID больше или равным (>=) переданным ID. Используется сравнение строк.

    • lt: ID: Получить объекты активностей с ID меньше (<) переданных ID. Используется сравнение строк.

    • lte: ID: Получить объекты активностей с ID меньше или равным(<=) переданным ID. Используется сравнение строк.

    • startsWith: String: Получить объекты активностей, чьи ID начинаются с переданного значения.

    • iStartsWith: String: Получить объекты активностей, чьи ID начинаются с переданного значения. Без учета регистра.

    • endsWith: String: Получить объекты активностей, чьи ID заканчиваются переданным значением.

    • iEndsWith: String: Получить объекты активностей, чьи ID заканчиваются переданным значением. Без учета регистра.

    • range: [ID!]: Получить объекты активностей, чьи ID находятся в диапазоне переданных ID. Используется сравнение строк.

    • isNull: Boolean: Получить объекты активностей, чьи ID равны(true) или не равны (false) нулю null.

    • regex: String: Получить объекты активностей, чьи ID соответствуют переданному регулярному выражению.

    • iRegex: String: Получить объекты активностей, чьи ID соответствуют переданному регулярному выражению. Без учета регистра.

  • creationDate: DatetimeFilterLookupCustom: Фильтрация по дате создания активности. Параметры аналогичны параметрам для фильтрации по ID.

  • lastModified: DatetimeFilterLookupCustom: Фильтрация по дате последнего изменения активности. Параметры аналогичны параметрам для фильтрации по ID.

  • profileId: ID: Фильтрация активностей по ID профиля.

order: ActivityOrdering: Вы можете настроить сортировку списка активностей:

  • id: Ordering: Сортировка по ID. Используется сравнение строк.(ASC: Сортировка по возрастанию, DESC: Сортировка по убыванию)
  • creationDate: Ordering: Сортировка по дате создания активности.
  • lastModified: Ordering: Сортировка по дате последнего изменения активности. pagination: OffsetPaginationInput:
  • limit: Int!: Параметр позволяет получить первые n активностей из списка.
  • offset: Int!: Параметр позволяет удалить первые n активностей из списка. ActivityOutputCountList!: Результат запроса - список активностей со следующими параметрами:
  • totalCount: Int!: Число возвращенных активностей.
  • collectionItems: [ActivityOutput!]!:
    • id: ID!: ID активности.
    • data: JSON: Дополнительная информация об активности.
    • lastModified: DateTime: Дата последнего изменения активности в формате ISO 8601.
    • creationDate: DateTime!: Дата создания активности в формате ISO 8601.
    • bestShotId: ID: ID лучшего изображения лица, полученного с камеры, обнаружившей активность (Отсутствует, если включен анонимный режим или камера не смогла обнаружить изображение лица).
    • cameraId: ID!: ID камеры, заметившей активность.
    • locationId: String!: ID локации, к которой привязана камера.
    • profileId: ID: ID профиля.
    • status: ActivityType!: Статус активности:
      • Progress (активность не завершена, человек находится в кадре)
      • Finalized (активность завершена, человек вышел из кадра)
      • Failed (отсутствие данных об обновлении или завершении активности со стороны агента)
  • timeStart: String!: Время начала активности
  • timeEnd: String!: Время завершения активности

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

{
activities(filters: {
id: {
exact: "78f7c795-0f28-42ce-a9d2-818095dd5f84"
}
}) {
totalCount
collectionItems {
id
data
cameraId
bestShotId
locationId
profileId
timeStart
creationDate
lastModified
}
}
}

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

API возвращает следующий результат:
{
"data": {
"activities": {
"totalCount": 1,
"collectionItems": [
{
"id": "78f7c795-0f28-42ce-a9d2-818095dd5f84",
"data": {
"processes": [
{
"id": "78f7c795-0f28-42ce-a9d2-818095dd5f84",
"type": "track",
"object": {
"id": "c4398bcc-6fee-495a-be86-a59918a875e5",
"class": "human"
},
"time_interval": [
"2022-07-07T12:36:51.644000+05:00",
"2022-07-07T12:36:51.725000+05:00"
]
},
{
"id": "ecb65ed1-e3c5-484f-b1e3-7f4bdf869757",
"type": "track",
"object": {
"id": "c4398bcc-6fee-495a-be86-a59918a875e5",
"age": 36,
"class": "face",
"gender": "MALE",
"quality": -1114.097412109375,
"embeddings": {
"$binary_image": {
"id": "7fd8abfb-258b-4d6a-bdd7-eec1e30fd0b4"
},
"$template10v100": {
"id": "35b60b5f-d6da-4998-ac4c-5725d3e64520"
}
}
},
"parent": "78f7c795-0f28-42ce-a9d2-818095dd5f84",
"sample_id": "3071e862-7116-4ed3-94f1-309b0b5b912f",
"$best_shot": {
"id": "ab8d76c8-0a8c-4575-8d81-e9e469f8ef64"
},
"time_interval": [
"2022-07-07T12:36:51.644000+05:00",
"2022-07-07T12:36:51.725000+05:00"
]
},
{
"id": "3e33004f-6531-40ca-90d5-8345f66002ac",
"type": "attention",
"parent": "ecb65ed1-e3c5-484f-b1e3-7f4bdf869757",
"time_interval": [
"2022-07-07T12:36:51.806000+05:00",
"2022-07-07T12:36:52.413000+05:00"
]
}
]
},
"cameraId": "3c818dc4-352c-47a7-b32b-465fbd4a9665",
"bestShotId": "ab8d76c8-0a8c-4575-8d81-e9e469f8ef64",
"locationId": "",
"profileId": "1cf13933-00be-4a6d-8dc3-3ff17f94aef8",
"timeStart": "2022-07-07T12:36:51.644000+05:00",
"creationDate": "2022-07-07T07:36:52.848815+00:00",
"lastModified": "2022-07-07T08:59:56.385040+00:00"
}
]
}
}
}

Создать профиль из активности

Мутация createProfileByActivity используется для создания профиля из активности.

createProfileByActivity(activityId: ID!
profileData: ProfileInput = null): ProfileCreateOutput!

activityId: ID!: ID активности, из которой должен быть создан профиль.

profileData: ProfileInput: Вы можете указать дополнительную информацию для сохранения в профиле:

  • profileGroupIds: [ID]: Список ID групп, к которым привязан новый профиль.
  • info: JSON: Дополнительная информация о профиле (age: Int, gender: "MALE" | "FEMALE")

ProfileCreateOutput: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean!: Атрибут успешного завершения мутации
  • profile: ProfileOutput!: Объект нового профиля.
  • isCreated: Boolean!: Определяет, был ли создан новый профиль, или фотография привязана к уже существующему профилю.

Ошибки входных данных:

  • Ошибка при попытке создать профиль из анонимной активности:
{
"message": "Activity is anonymous",
"code": "0x358vri3s"
}
  • Активность не найдена по переданному ID:
{
"message": "Activity matching query does not exist."
}
  • Группы не найдены по переданным ID:
{
"message": "One or several profiles_groups does not exist",
"code": "0x573bkd35"
}

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

mutation{
createProfileByActivity(activityId: "78f7c795-0f28-42ce-a9d2-818095dd5f84") {
ok
isCreated
profile{
id
}
}
}

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

API возвращает следующий результат:
{
"data": {
"createProfileByActivity": {
"ok": true,
"isCreated": false,
"profile": {
"id": "1cf13933-00be-4a6d-8dc3-3ff17f94aef8"
}
}
}
}

Агенты

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

Запрос agents позволяет получить список агентов.

agents( filter: JSON = null
ids: [ID] = null
limit: Int = null
offset: Int = null
order: [String] = null
withArchived: WithArchived = null): AgentsCollection!

filter: JSON: Вы можете отфильтровать список агентов, указав значения для одного или нескольких параметров:

  • activations:
  • cameras: ID камеры, сохраненный в базе данных.
  • creation_date: Точная дата создания агента в формате ISO 8601
  • id: ID агента, сохраненный в базе данных.
  • info__title: Название агента.
  • is_active: Атрибут активности агента.
  • last_modified: Точная дата последнего изменения агента в формате ISO 8601
  • workspace: ID воркспейса
  • workspace_id: ID воркспейса

ids: [ID]: Для получения списка конкретных агентов укажите их ID в списке.

limit: Int: Параметр позволяет получить первые n агентов из списка.

offset: Int: Параметр позволяет удалить первые n агентов из списка.

order: [String]: Вы можете отсортировать список, указав значения для следующих параметров: activations, cameras, creation_date, id, info, is_active, last_modified, workspace, workspace_id.

withArchived: WithArchived: Для получения списка всех агентов, в том числе заархивированных,укажите значение all. Для получения списка только заархивированных агентов укажите значение archived.

AgentsCollection!: Результат запроса - список агентов со следующими параметрами:

  • totalCount: Int: Число возвращенных агентов
  • collectionItems: [AgentsCollection!]!:
    • id: ID!: ID агента
    • creationDate: DateTime!: Дата создания агента в формате ISO 8601.
    • lastModified: DateTime!: Дата последнего изменения агента в формате ISO 8601.
    • token: String!: Токен агента
    • camerasIds: [ID!]: Список ID камер, подключенных к агенту.
    • title: String: Название агента
    • agentStatus: String!: Статус агента
    • agentLastActiveTime: String: Дата последней активности, зафиксированной камерой агента.
    • archived: Boolean!: Атрибут архивации агента.

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

{
agents {
totalCount
collectionItems {
token
title
lastModified
id
creationDate
camerasIds
archived
agentStatus
agentLastActiveTime
}
}
}

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

API возвращает следующий результат:
{
"data": {
"agents": {
"totalCount": 1,
"collectionItems": [
{
"token": "19df2b38-7d23-44a5-85e7-c5a29b304581",
"title": "My Agent",
"lastModified": "2022-07-12T08:50:45.296225+00:00",
"id": "19df2b38-7d23-44a5-85e7-c5a29b304581",
"creationDate": "2022-07-07T07:23:08.965949+00:00",
"camerasIds": [
"3c818dc4-352c-47a7-b32b-465fbd4a9665"
],
"archived": false,
"agentStatus": "active",
"agentLastActiveTime": "2022-07-12T08:50:45.296115"
}
]
}
}
}

Создать агент

Мутация createAgent позволяет создать агент.

createAgent(agentData: AgentInput!): AgentCreateOutput!

agentData: AgentInput!: Информация, которая потребуется для создания агента:

  • title: String: Название агента.
  • extra: JSON: Дополнительная информация об агенте.

AgentCreateOutput: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean!: Атрибут успешного завершения мутации.
  • agent: AgentOutput!: Объект нового агента.
  • channelCost: String: Ежемесячная плата за обслуживание.
  • writeoffDate: String: Дата следующего обслуживания в формате ISO 8601.

Ошибки входных данных:

  • Ошибка при создании агента из-за превышения лимита созданных агентов:
{
"message": "Agent limit exceeded",
"code": "0x6245cd00"
}
  • Переданы неверные дополнительные данные:
{
"message": "'int' object has no attribute 'get'"
}

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

mutation{
createAgent(agentData: {title: "My new agent"}) {
ok
agent {
id
}
}
}

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

API возвращает следующий результат:
{
"data": {
"createAgent": {
"ok": true,
"agent": {
"id": "2b769e5a-a49a-46ac-ac38-ec924bd4ec83"
}
}
}
}

Обновить агент

Мутация updateAgent используется для обновления информации об агенте.

updateAgent(agentData: AgentUpdateInput!
agentId: ID!): AgentManageOutput!

agentData: AgentUpdateInput!: Информация, которая потребуется для обновления агента:

  • title: String: Название агента.

agentId: ID!: ID агента, который необходимо обновить.

AgentManageOutput: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean!: Атрибут успешного завершения мутации.
  • agent: AgentOutput!: Объект обновленного агента.

Ошибки входных данных:

  • Агент не найден по переданному ID:
{
"message": "Camera matching query does not exist."
}

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

mutation{
updateAgent(
agentId: "19df2b38-7d23-44a5-85e7-c5a29b304581",
agentData: {
title: "My old agent"
}) {
ok
agent {
id
title
}
}
}

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

API возвращает следующий результат:
{
"data": {
"updateAgent": {
"ok": true,
"agent": {
"id": "19df2b38-7d23-44a5-85e7-c5a29b304581",
"title": "My old agent"
}
}
}
}

Удалить агенты

Мутация deleteAgent позволяет удалить один или несколько агентов.

deleteAgent(agentId: ID = "" agentIds: [ID!] = null): MutationResult!

agentId: ID: ID агента, который требуется удалить.

agentIds: [ID!]: Список ID агентов, которые требуется удалить.

MutationResult!: Результат мутации - JSON-файл со следующими параметрами:

  • ok: Boolean!: Атрибут успешного завершения мутации.

Ошибки входных данных:

  • Не передан ID для удаления агента:
{
"message": "One of the parameters agentId or agentIds is required",
"code": "0xe509f74d"
}

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

mutation{
deleteAgent(agentId: "19df2b38-7d23-44a5-85e7-c5a29b304581") {
ok
}
}

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

API возвращает следующий результат:
{
"data": {
"deleteAgent": {
"ok": true
}
}
}

Другое

Получить ссылки на аналитику

Запрос analytics позволяет получить ссылки на аналитику.

analytics: AnalyticsOutput!

AnalyticsOutput!: Результат запроса - список ссылок:

  • retail: String: ссылка на Аналитику аудитории.
  • advertising: String: ссылка на Цифровую рекламу.

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

{
analytics {
advertising
retail
}
}

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

API возвращает следующий результат:
{
"data": {
"analytics": {
"advertising": "http://192.168.45.59:5601/s/8d100a02-1b5b-4da1-b645-9fd01ef09c77/app/dashboards#/view/advertising_analytics",
"retail": "http://192.168.45.59:5601/s/8d100a02-1b5b-4da1-b645-9fd01ef09c77/app/dashboards#/view/retail_analytics"
}
}
}

Получить информацию о пользователе

Запрос me позволяет получить информацию об авторизованном пользователе.

me: UserType!

UserType!: Результат запроса - список ссылок:

  • username: String!: Логин.
  • email: String!: Почта пользователя.
  • firstName: String!: Имя пользователя.
  • lastName: String!: Фамилия пользователя.
  • workspaces: [WorkspaceType!]!: Информация о воркспейсах пользователя.

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

{
me {
email
firstName
lastName
username
workspaces {
id
}
}
}

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

API возвращает следующий результат:
{
"data": {
"me": {
"email": "aa@aa.ru",
"firstName": "",
"lastName": "",
"username": "aa@aa.ru",
"workspaces": [
{
"id": "8d100a02-1b5b-4da1-b645-9fd01ef09c77"
}
]
}
}
}