Skip to main content

Integration API

All available face recognition operations with OMNI Platform objects (such as Profiles, Profile Groups, Samples, etc.) can be performed using Integration API. Access to API is enabled via GraphQL - an open-source API data query and manipulation language and a runtime for running existing data queries. With GraphQL you can send requests to OMNI Platform and receive the requested data that can be integrated into your client application. For more information about GraphQL see the following sources:

To get started with API, sign in to OMNI Platform account. If you have no account, go to Sign Up page.

To use Integration API in your application, add Token to HTTP request header and send request to the https://cloud.3divi.ai/api/v2/. To get the token, follow the instructions below:

  1. Open GraphQL interactive console by clicking Platform API button at Resources widget of web interface.
  2. Copy the request below to the console and click Execute Query button.
query{
me {
workspaces {
accesses {
id
}
}
}
}
  1. As a result, GraphQL returns the response with a token (id):
{
"data": {
"me": {
"workspaces": [
{
"accesses ": [
{
"id": "3460***"
}
]
}
]
}
}
}
note

The user registered with PLATFORM_DEFAULT_EMAIL can get API access token via a command:

$ ./setup/get-token.sh

For more details follow the Administrator Guide.

cURL requests

Except for GraphQL you can send the requests using cURL. cURL template for sending API requests is given below:

curl --location --request POST "<url>" --header "token: <your access token>" --header "Content-Type: application/json" --data-raw "{\"query\":\"<GraphQL query or mutation>\",\"variables\":{<GraphQL variables>}}"

<url> - URL of your server

<your access token> - note that your cURL requests will not be sent without access token.

Example cURL request: This request is used to get a list of first 5 profiles from the database.

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 returns the following result:

{
"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"
}
}
]
}
}
}

The requests and responses for API testing in GraphQL are given below.

Face Recognition

General Incorrect Input Errors

Errors Occured When Uploading an Image Via API:

  • Invalid base64 string:
{
"message": "image file is truncated (21 bytes not processed)"
}
  • Image not transferred in base64:
{
"message": "Expected value of type 'CustomBinaryType', found \"wrong_data\";
}
  • No image transmitted:
{
"message": "Sample Data is not valid",
"code": "0xc69c44d4"
}
  • Image uploaded in an incorrect format:
{
"message": "Image decode failed"
}
  • No faces detected in the image:
{
"message": "No faces found",
"code": "0x95bg42fd"
}
  • Too big image size:
Bad Request (400)

Errors Occured in Filtering, Pagination and Sorting of Objects:

  • Transmitted filters are not in dictionary format:
{
"message": "'str' object has no attribute 'keys'"
}
  • Invalid field used for filtering:
{
"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"
}
  • Using an invalid field to filter sub-objects or a function over a field:
{
"message": "Unsupported lookup '1' for UUIDField or join on the field not permitted."
}
  • Negative value specified in the pagination fields:
{
"message": "Negative indexing is not supported."
}
  • Invalid field used for ordering:
{
"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"
}

Remaining General Errors:

  • Object id given in a non-UUID format:
{
"message": "“%(value)s” is not a valid UUID."
}
  • Transmitted JSON did not pass validation by JSON schema:
{
"message": "Invalid JSON request"
}

Face Detection and Processing

This query allows to detect multiple faces in the image, estimate facial attributes (such as gender, age, emotions, liveness, mask presence, etc.) and create samples.

processImage(image: CustomBinaryType!): ImageProcessInfo!

image: CustomBinaryType!: Base64 encoded image

ImageProcessInfo!: API returns a file in JSON format that contains the following fields:

faces:[FaceProcessInfo!]!: Information on face detection and processing is represented in the following fields:

  • id: Int!: Face identification number. Each face has a unique id within the list
  • class: String!: Object type. The object for current API always has a face type
  • confidence: Float!: Face detection confidence
  • bbox: [Float!]!: Bounding box. The rectangle that represents face bounds in the image. The bounds are calculated relative to the coordinates of the original image. The first two bbox coordinates are X and Y of the left top point, the second two are X and Y of the right bottom point
  • cropImage: String!: Thumbnail image. Face image in base64 format cropped from an extended bbox
  • fitter: Fitter!: Anthropometric points
    • fitter_type:: Type of set of anthropometric points. The fda provides high accuracy in a wide range of facial angles (up to the full profile), however, the recognition algorithms still require that the facial perspective is as close to the full face as possible. The fda set contains 21 points
    • keypoints: Facial anthropometric points. List of repeated X, Y and Z coordinates relative to the original image
    • left_eye: Left eye center X and Y coordinates relative to the original image
    • right_eye: Right eye center X and Y coordinates relative to the original image
  • emotions: [Emotions!]! Estimation of emotions from a face image
    • confidence: String! Numerical value of manifestation of each estimated emotion
    • emotion: String! Emotion type: angry, disgusted, scared, happy, neutral, sad, surprised
  • mask: MaskConfidenceValue! Estimation of face mask presence/absence
    • confidence: String! Numerical value of confidence that a person in the image is/isn’t wearing a mask
    • value: Boolean! Verdict: true - masked person, false - unmasked person
  • templates: Templates! Biometric template coded in base64 used for face comparison
  • gender: String! Gender estimation from a face image
  • age: String! Age estimation from a face image
  • angles: Angles! Head rotation angles. 3DiVi algorithms allow to detect faces in the following range of angles: yaw [-60; 60], pitch [-60; 60], roll [-30; 30]
    • yaw: String! Rotation around the vertical axis Y
    • roll: String! Rotation around the horizontal axis X
    • **pitch: String! Rotation around the horizontal axis Z
  • liveness: LivenessConfidenceValue! Estimation that a person in the image is real or fake
    • confidence: String! Numerical value of confidence that the image belongs to a real person
    • value: String! Verdict: REAL - the face image belongs to a real person, FAKE - the face image doesn’t belong to a real person
  • quality: Quality! Information about image quality
    • qaa: Qaa! Quality assessment algorithm operates with the following data:
      • totalScore: Int! Numerical value that represents the score of overall image quality from 0 to 100
      • isSharp: Boolean! Boolean value that represents the image sharpness
      • sharpnessScore: Int! Numerical value that represents the sharpness score from 0 to 100
      • isEvenlyIlluminated: Boolean! Boolean value that represents the illumination uniformity in the image
      • illuminationScore: Int! Numerical value that represents the illumination uniformity score from 0 to 100
      • noFlare: Boolean! Boolean value that represents presence/absence of image flares
      • isLeftEyeOpened: Boolean! Boolean value that represents the position of left eye (open/closed)
      • leftEyeOpennessScore: Int! Numerical value that represents the degree of left eye openness in points from 0 to 100
      • isRightEyeOpened: Boolean! Boolean value that represents the position of right eye (open/closed)
      • rightEyeOpennessScore: Int! Numerical value that represents the degree of right eye openness in points from 0 to 100
      • isRotationAcceptable: Boolean! Boolean value for acceptable/ unacceptable values of yaw, pitch and roll angles
      • maxRotationDeviation: Int! Numerical value that represents the maximum degree of deviation for yaw, pitch and roll angles
      • notMasked: Boolean! Boolean value for presence/absence of a face mask
      • notMaskedScore: Int! Numerical value of confidence that a person in the image isn’t wearing a mask in points from 0 to 100
      • isNeutralEmotion: Boolean! Boolean value for presence/absence of neutral emotions
      • neutralEmotionScore: Int! Numerical value for score of neutral emotions in points from 0 to 100
      • isEyesDistanceAcceptable: Boolean! Boolean value that represents the allowable/unallowable distance between eyes
      • eyesDistance: Int! Numerical value that represents the distance between eyes in pixels
      • isMarginsAcceptable: Boolean! Boolean value that represents allowable/unallowable margins
      • marginOuterDeviation: Int! Numerical value of outer deviation in pixels
      • marginInnerDeviation: Int! Numerical value of inner deviation in pixels
      • isNotNoisy: Boolean! Boolean value that indicates presence/absence of noise in the image
      • noiseScore: Int! Numerical value that represents the score of image noise in points from 0 to 100
      • watermarkScore: Int! Numerical value of confidence that the image contains a watermark in points from 0 to 100
      • hasWatermark: Boolean! Boolean value for presence/absence of watermark in the image
      • dynamicRangeScore: Int! Numerical value that represents the score of dynamic range of intensity in points from 0 to 100
      • isDynamicRangeAcceptable: Boolean! Boolean value that represents that the dynamic range of image intensity in the face area exceeds/doesn’t exceed the value of 128
      • isBackgroundUniform: Boolean! Boolean value for background uniformity
      • backgroundUniformityScore: Int! Numerical value for background uniformity score in points from 0 to 100

sample:JSON! Result of face detection and processing in sample format. The sample contains the uploaded image in base64 format and a list of above-mentioned faces fields.

Example Request:

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

Example Response:

API returns the following result:
  {
"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": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCABYAFwDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwC+YonU4yTUQiAYADAotXfNW3Qdc4NQjdoiRMEgUsi4FPG1Rkml3I/Ga1I6kNuNjnKgAck4qhqXiWztldCJGwOqjHP1NWdTuPsmnyuoYuw2IqDLMT2A9a5TxF4b1TStIivr04d2G+PHKA9Mnp6cU00tAae6MjU/FU11JtQ+QmB97k1gz3DStlmYt2OaSRt2C4yw7moiF25zj2FLlS2LliKr0b0JbPUJ7W6BJRlBxyMjPB5/Ct9Z0uYyEJBA6A8g/WuUkAcYwKda38lpIeXweprGpTvqj3MpzeVH91U2O6tLppbdFdy7N93J5B9j6cYq7DOk0YZ3CnpWBY3Eb2SOD97OR6VMzytI7RCEqxz+8yCCR7dqiLPoczorEYeDgrv9D0ZUEe4j1qEzcnJpPtIEWDyTVYuAMjk1o5HwRaeX5R8oqFSfPGCQD2pFl3ACpIk3zqhdULYCs3Tnimplcp1vh/TgSuoSKMocRZHI/wBqo/Ftg2peH7q3UAu6EqT6jkfqBUun6hPb6aVvDGJIAUZox8rehA+lU7XxVpepq0LTGByCAJRgfnUud2XGnZHz5IpbIIwT29KrOGil2yLkY4Jre8S2cem+JL63SRWi370ZTkbWwcD6ZI/Cq+rW6SWdnKFxvQqWAxlhx/ga15tTn5NzDaQCqsx3A4qRz7Y9qgc1RJvaZP8A6LEgOMDn861RqM1uipG5UYzwepz1rltPuvKbaT9K2GxIqNuzla4qisz7PLsXzUUo7o9MG9uMdKUqyKSSc1p3FukWGUjnniqpXzCRiqPlOVJFWAu7cZrbsvD99q0BmguJLYwHcjpgliO2COR61UhhEbjgCu3s9SsbLTYIndI2CAnJ9e9NabjjFvYzbfRLyz0h7e/vBeXkrl3dI9qqP7vHXnviuWPiW3sAdPv7CQSq5Ta0BcP7gru/UCvRI5ITMjeaknmdCpBzT5dPsTL57QqZB/GQM0W6m13HQ8F8d2EO6DUrG1MMUrFJF2H5G7cHp349qoSRrc+FopF3M0U5zj0I6/zr2LxpZRan4fu7VVyzISmecEHI/UCvI/D8ynStQ02bg4yM8EEEf1qk9CHH3m+5xcqFju/Oq0grRePEjoeBuOKsWehPeEgyMcg7Vij3E/U9BWvNY5uRt2RgA4bjrXT6bAkljG0rMGPpWFd2T2t06MdwGCpA6g8itqH7SkKAQSkYGMA4xWU2merlLUJyc+h6te3xlbC8H2pbAM5JYk89zWdK2GGDV2wm2NyayijgsbHl7UyakawmvrMywWSXjSRGJ4mIGAp6jOOeRVV7oMMA1p2dlfT6WoiBWOSRiCrMD2HUfjWjNsM0p7/eUNPvdN0yWNbmyutMuUOI/tGfLPfAIJHSt/8AtRp0G3kMMg0xtEkuofKvrmRogMNG2OeMdcZoNtDbBIreNUiiARVUdAOAKhs6J8jloEwaS1dXznbXkHijTjpt8L+JThmKSAeh7165cTKYmXdya4/xFDFNatDjOTg1KdmZyjdHnOoWCC1FxECxxkd81d8Py/YLo3XmBVEJZ9x4C9MfhyfwxVizuUtbK5sJ4iIwSUYjhlHUfXpXOWk4edrZ/wDVkHA/lW+6Od+47oz9Xvxe6vLdQp5UTNiND2VRhc++BzXXaFr18dLRXtUk2kqr4xkVxE0WyaRMfxnH512WjOIdKgVuCRnmiUVsFG7k5M7K6jxIopYUIb5ST7U6+kBudo7VNYJnJPNZAB83eCF4Fd5Ya7bxaZbxMQCkSqR6HHNcxHDntStbKuSe9Q52BSj9pHQza9AwwpAHtVCbU4mHDgVmRRRmZVMeVyBnFRvpA83GWxn1qeZs6acoPoTyXayE7Dk5qjc2z3HJyBWpbaWkZ6GrU9sFgKhRz7Uy5SSeh5vrFiZZ0tR8scZklDD/AHRn/wBBH61wllG8msRKByzGvW76xCw3V5MwWJEdcH0AI/mTXILpsFnNHcRRZkEZbpnrjmtYSsjmqQbaOSmtHN9KuMsH2810rxrFtjXlVUAVBFaSPqMnyEl3BB69q14bIlD5kTZz3FNzOrE0Y04QS6m/OmJwx71egIRNwGAPSiipOItw3q7TUhuQyjPNFFYzQWHwSF5UAPG9ePxroFhDztngCiiqhoi4aOy6iXUsFvF87qgxktu7Vymq+NLSMFLKEzkHAkc7V9OO5ooobPfy7BUqrfP0OZ1G6u760mWaYsBbuSg4X7y5/mal0tRJYJOXDSMgB2n7px0ooqmTnFGFKPuK1i5HaxvdRStHgoM/LwG+taCLEFAIHHFFFSz56dST3Z//2Q==",
"angles": {
"yaw": -40.34304428100586,
"roll": 12.045698165893555,
"pitch": -16.30009651184082
}
}
]
}
}
}
}

Face Detection

This query allows you to detect multiple faces in the image and get information about these faces (such as gender, age, emotions, liveness, mask presence, etc.). You can use this query if you're interested in detection result only, without saving it in your local database.

Attention! This query will be available until 2024.

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

image: CustomBinaryType!: Base64 encoded image
pupils: [EyesInput!]: To increase face detection accuracy, you can specify X and Y coordinates of eye pupuls.

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

JSON! : API returns a sample in JSON format that contains the following parameters:

  • image: Base64 encoded image
  • id: The ordinal number of a face in the image
  • class: Object class name, e.g., face
  • template: A unique set of biometric features extracted from a face image. Templates are used to compare two face images and to determine a degree of similarity.
  • bbox: A rectangle that surrounds a face and specifies face position and size in the original image.
  • crop image: To determine face features, the system crops the uploaded image to extract face images. These extracted face images are called crop images.
  • keypoints: A collection of 21-point face landmarks pointing to the positions of face components.
  • rotation angles: Yaw (rotation along Z axis), pitch (rotation along Y axis), and roll (rotation along X axis) rotation angles. OMNI Platform algorithm allows to detect faces in the following range of angles: yaw [-60; 60], pitch [-60; 60], roll [-30; 30]
  • age: Age in years
  • gender: Possible gender of a person in the image
  • emotions: Facial emotions described in a form of confidence
  • liveness: Integrated liveness algorithm allows to detect if a person in the image is real or fake.
  • mask presence: The system can detect if a person in the image is wearing a mask.

Example Request:

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

Example Response:

API returns the following result:
  {
"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
}
}
]

}
}
}

Create a Sample

This mutation allows you to create samples and get information about faces in created samples (such as gender, age, emotions, keypoints, liveness, mask presence, etc.). The created sample is automatically saved at OMNI Platform Server.

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

anonymousMode: Boolean = false : If you have to work with anonymous data, you can set anonymousMode to true (by default, it's set to false). In this case, the image is not saved at OMNI Platform Server.

image: CustomBinaryType : Base64 encoded image

pupils: [EyesInput!] : To increase face detection accuracy, you can specify X and Y coordinates of eye pupuls.

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

sampleData: JSON : Sample data is the face detection result, not saved at the database.

SampleOutput! : API returns JSON file with the following fields:

  • id : Sample ID
  • creationDate : Sample creation date in ISO 8601 format with time zone
  • lastModified : Last sample modification date in ISO 8601 format with time zone
  • data : Image and/or template and/or detection result in sample format

The returned sample is automatically saved at OMNI Platform Server (if anonymousMode is set to false) and can be used to verify a face to a face or seach a person in the database.

Incorrect input errors:

  • No data has been entered to create a sample:
{
"message": "One of the parameters sampleData or sourceImage is required",
"code": "0xnf5825dh"
}
  • Invalid transmitted sample data:
{
"message": "argument should be a bytes-like object or ASCII string, not 'NoneType'"
}
  • Transmitted wrong pupils coordinates:
{
"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."
}

Example Request:

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

Example Response:

API returns the following result:
{
"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
}
]
}
}
]
}
}

Face Verification

Query verify() is used to compare two samples and verify whether two face images belong to the same person or whether one face image belongs to the person.

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

sourceImage: CustomBinaryType : Base64 encoded image

sourceSampleData: JSON : Face detection result, not saved at the database.

sourceSampleId: ID : Sample ID to be compared with target sample ID

targetSampleId: ID : Sample ID to be compared with a source image, source sample data or source sample ID

MatchResult : Verification result that contains the following parameters:

  • distance: The parameter shows the distance between the compared template vectors. The shorter the distance, the higher the verification rate is.

  • faR : False acceptance rate (FAR) shows the system resistance to false acceptance errors. Such an error occurs when the biometric system recognizes a new face as previously detected one. This rate is measured by the number of false-acceptance recognitions divided by the total number of recognition attempts.

  • frR : False rejection rate (FRR). When a system fails to recognize previously detected face, false rejection occurs. The rate shows the percentage of recognition attempts with false rejection result.

  • score: The parameter shows the verification rate from 0 (0%) to 1 (100%)

Incorrect input errors:

  • A comparison object is not passed or an ambiguous interpreted combination is passed:
{
"message": "One of the parameters sourceSampleData or sourceSampleId or sourceImage is required",
"code": "0x963fb254"
}
  • No sample found by transmitted id:
{
"message": "Sample matching query does not exist."
}
  • Transmitted source sample data is invalid:
{
"message": "'objects@common_capturer_uld_fda'"
}

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"verify": {
"distance": 0,
"faR": 0,
"frR": 1,
"score": 1
}
}
}

Face Identification

This query allows you to search for a person in the database. Function search() is used to compare one sample with all other samples in the database.

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

confidenceThreshold: Float = 0 : To exclude matches with low confidence from the returned result, use the confidenceThreshold parameter (min: 0, max: 1; default: 0)

maxNumOfCandidatesReturned: Int = 5 : To set the max number of returned candidates, specify the value for the maxNumOfCandidatesReturned parameter (min: 1, max: 100). By default, 5 closest candidates are returned.

scope: ID : By default, a person is searched in an entire database. To get matches from a specific List, set the List id in the scope parameter.

sourceImage: CustomBinaryType : Base64 encoded image

sourceSampleData: JSON : Face detection result, not saved at the database.

sourceSampleIds: [ID!] : Sample IDs

SearchType! : The result is a list of candidates for each requested sample in descending order of confidence. Search result contains the following parameters:

  • 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!)

Note: the source data is compared with Profiles from the server, not with the samples. So, before you start searching, make sure you have created at least 1 profile.

Example Request:

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

Example Response:

API returns the following result:
{
"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"
}
}
}
]
}
]
}
}

Note that if the database contains no profiles created before search start, the profile field in the returned result will be blank.

The searchInActivities query allows you to search for a person by activity.

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

confidenceThreshold: Float = 0: To exclude matches with low confidence from the returned result, use the confidenceThreshold parameter (min: 0, max: 1; default: 0)

maxNumOfCandidatesReturned: Int = 5: To set the max number of returned candidates, specify the value for the maxNumOfCandidatesReturned parameter (min: 1, max: 100). By default, 5 closest candidates are returned.

sourceImage: CustomBinaryType: Base64 encoded image

sourceSampleData: JSON: face detection result, not saved at the database.

sourceSampleIds: [ID!]: Sample IDs

ActivitySearchType!: The result is a list of candidates for each requested sample in descending order of confidence. Search result contains the following parameters:

  • 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! )

Note: The search is performed only on activities with the FINALIZED and FAILED status, for which a biometric template has been extracted.

Example Request:

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

Example Response:

API returns the following result:
{
"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
}
}
]
}
]
}
}

Incorrect input errors

  • A comparison object is not passed or an ambiguous interpreted combination is passed:
{
"message": "One of the parameters sourceSampleData or sourceSampleId or sourceImage is required",
"code": "0x963fb254"
}
  • The confidenceThreshold value is transmitted out of range:
{
"message": "Confidence threshold must be between 0 and 1",
"code": "0xf47f116a"
}
  • The maxNumOfCandidatesReturned value is transmitted out of range:
{
"message": "Max num of candidates must be between 1 and 100",
"code": "0xf8be6762"
}
  • Transmitted source sample data is invalid:
{
"message": "'objects@common_capturer_uld_fda'"
}

Profiles

Get Profiles

Query profiles() allows you to get a list of all created profiles.

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

filter: JSON: You can filter a profile list by specifying one or several parameters:

  • creation_date: Exact profile creation date in ISO 8601 format
  • id: ID assigned to a profile from the database
  • info: Object with the following parameters:
    • age: Profile age. For example, a request with a parameter info_age:28 returns a list of profiles with age equal to 28.
    • gender: Profile gender. For example, a request with a parameter info_gender: “MALE” returns a list of male profiles.
    • main_sample_id: ID assigned to the best profile sample.
    • avatar_id: ID of profile avatar.
  • last_modified: Exact date of the last profile modification in ISO 8601 format
  • link_to_label:
  • person:
  • person_id: ID assigned to a profile from the database
  • profile_groups: List of group IDs
  • samples: Sample ID
  • workspace: Workspace ID
  • workspace_id: Workspace ID

ids: [ID]: To get a list with certain profiles, specify their IDs in the list.

limit: Int: The parameter allows to get the first n profiles from the list.

offset: Int: The parameter allows to exclude the first n profiles from the list.

order: [String]: You can sort the list by specifying the value for the following parameters: creation_date, id, info, last_modified, link_to_label, person, person_id, profile_groups, samples, workspace,workspace_id.

ProfilesCollection!: The query result is a profile list that contains the following parameters:

  • totalCount: Number of returned profiles
  • collectionItems: [ProfileOutput!]
    • id: Profile ID
    • lastModified: Last profile modification date in ISO 8601 format
    • creationDate: Profile creation date in ISO 8601 format
    • info: Profile information (approximate age, gender, avatar ID, the best sample ID)
    • samples: List of profile samples
    • profileGroups: List of profile groups
    • mainSample: The best profile sample
    • avatar: Profile avatar
    • activities: All profile activities
    • activitiesCount: Number of profile activities
    • firstActivityDate: The first profile activity date recorded by the system in IS O8601 format
    • lastActivityDate: The last profile activity date recorded by the system in ISO 8601 format

Example Request:

{
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
}
}
}
}

Example Response:

API returns the following result:
{
"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"
}
]
}
]
}
}
}

Сreate a Profile

Mutation createProfile() is used to create a new profile. The created profile is automatically saved at OMNI Platform Server.

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

image: CustomBinaryType: To add an avatar to a new profile, submit a base64 encoded image with the size up to 8MB.

profileData: ProfileInput: To add the supplemental information to be saved at the new profile, submit the following parameters:

  • profileGroupIds: [ID]: List of IDs assigned to groups which a new profile is linked to
  • info: JSON: Additional infromation about profile (age: Int, gender: "MALE" | "FEMALE")

ProfileCreateOutput!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean: Flag that mutation is successfully completed
  • profile: ProfileOutput!: New profile object
  • isCreated: Boolean!: The parameter determines whether a new profile is created or a photo is attached to the existing profile.

Incorrect input errors:

  • Image is transmitted in poor quality:
{
"message": "Low quality photo",
"code": "0x86bd49dh"
}
  • Profile groups not found by passed ids:
{
"message": "One or several profiles_groups does not exist",
"code": "0x573bkd35"
}

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"createProfile": {
"isCreated": true,
"ok": true,
"profile": {
"id": "d5ca09fb-199a-471f-99ca-b9b4954fb45f"
}
}
}
}

Update a Profile

Mutation updateProfile() is used to update profile information.

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

profileData: ProfileInput!: Profile information to be updated (profileGroupIds: [ID], info: JSON)

profileId: ID: Profile ID

ProfileUpdateOutput!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean: Flag that mutation is successfully completed
  • profile: ProfileOutput!: Updated profile object

Incorrect input errors:

  • Profile not found by passed id
{
"message": "Profile matching query does not exist."
}
  • Profile groups not found by passed ids
{
"message": "One or several profiles_groups does not exist",
"code": "0x573bkd35"
}

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"updateProfile": {
"ok": true,
"profile": {
"id": "d5ca09fb-199a-471f-99ca-b9b4954fb45f"
}
}
}
}

Delete a Profile

Mutation deleteProfiles() is used to delete profiles.

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

profileIds: [ID!]: List of IDs assigned to profiles to be deleted

MutationResult!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean: Flag that mutation is successfully completed

Incorrect input errors:

  • List of profile ids passed for deletion is empty:
{
"message": "Empty profiles ids list",
"code": "0xd2ae0ef8"
}

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"deleteProfiles": {
"ok": true
}
}
}

Profile Groups

Get Profile Groups

Query profileGroups() allows to get a list of all groups stored in the database.

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

filter: JSON: You can filter a group list by specifying one or several parameters:

  • area_type:
  • attention_areas:
  • camera_location:
  • cameras:
  • creation_date: Exact group creation date in ISO 8601 format
  • id: ID assigned to a group from the database
  • info: JSON completely similar to info parameter of a group object
  • last_modified: Exact date of the last group modification in ISO 8601 format
  • link_to_profile:
  • profiles: List of profile IDs
  • title: Group name
  • type:
  • workspace: Workspace ID
  • workspace_id: Workspace ID

ids: [ID]: To get a list of certain groups, specify their IDs in the list.

limit: Int: The parameter allows to get the first n profiles from the list.

offset: Int: The parameter allows to remove the first n profiles from the list.

order: [String]:

ProfileGroupsCollection!: The mutation result is a group list that contains the following parameters:

  • totalCount: Number of returned groups
  • collectionItems: [ProfileGroupOutput!]!:
    • id: Group ID
    • title: Group name
    • info: Additional group information in JSON format
    • lastModified: Last group modification date in ISO 8601 format
    • creationDate: Group creation date in ISO 8601 format
    • profileIds: List of IDs assigned to profiles which are linked to a group

Example Request:

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

Example Response:

API returns the following result:
{
"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"
}
]
}
}
}

Create a Profile Group

Mutation createProfileGroup() is used to create a new group. The created group is automatically saved at OMNI Platform Server.

createProfileGroup(profileGroupData: ProfileGroupInput!): ProfileGroupModifyOutput!

profileGroupData: ProfileGroupInput!: JSON with the information required for creating a new group:

  • title: String!: New group name
  • info: JSON = null: Additional group information

ProfileGroupInput!: The mutation result is JSON with the following parameters:

  • ok: Boolean: Flag that mutation is successfully completed
  • profileGroup: ProfileGroupOutput: New group object

Example Request:

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

Example Response:

API returns the following result:
{
"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"
}
}
}
}

Delete a Profile Group

Mutation deleteProfileGroup() allows to delete a group list.

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

groupIds: [ID!]!: List of IDs assigned to groups to be deleted

MutationResult!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean: Flag that mutation is successfully completed

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"deleteProfileGroup": {
"ok": true
}
}
}

Update a Profile Group

Mutation updateProfileGroupInfo() is used to update group information.

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

profileGroupData: ProfileGroupModifyInput!: JSON with the information to be updated:

  • title: Group name
  • info: Additional information about group

profileGroupId: ID!: Group ID

ProfileGroupModifyOutput!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean: Flag that mutation is successfully completed
  • profileGroup: ProfileGroupOutput: Updated group object

Incorrect input errors:

  • Profile group not found by transmitted id:
{
"message": "Label matching query does not exist."
}

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"updateProfileGroupInfo": {
"ok": true,
"profileGroup": {
"id": "800f0b65-7dbe-42b2-8f66-89af95a734e7",
"title": "New group's name"
}
}
}
}

Add Profiles to Profile Groups

Mutation addProfilesToGroups() allows to add the selected profiles to one or several shared groups.

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

groupIds: [ID!]!: List of group IDs

profilesIds: [ID!]!: List of profile IDs

ProfilesUpdateOutput!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean: Flag that mutation is successfully completed
  • profiles: [ProfileOutput!]!: List of updated profiles

Incorrect input errors:

  • Profile not found by passed id:
{
"message": "Profile matching query does not exist."
}
  • Profile groups not found by passed ids:
{
"message": "One or several profiles_groups does not exist",
"code": "0x573bkd35"
}

Example Request:

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
}
}
}
}

Example Response:

API returns the following result:
{
"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"
}
]
}
]
}
}
}

Remove Profiles from Profile Groups

Mutation removeProfilesFromGroups() is used to remove the selected profiles from one or several groups.

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

groupIds: [ID!]!: List of group IDs

profilesIds: [ID!]!: List of profile IDs

ProfilesUpdateOutput!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean: Flag that mutation is successfully completed
  • profiles: [ProfileOutput!]!: List of updated profiles

Incorrect input errors:

  • Profile not found by passed id:
{
"message": "Profile matching query does not exist."
}
  • Profile groups not found by passed ids:
{
"message": "One or several profiles_groups does not exist",
"code": "0x573bkd35"
}

Example Request:

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
}
}
}
}

Example Response:

API returns the following result:
{
"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

Get Endpoints

Query endpoints() allows to get a list of endpoints where notifications can be sent to.

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

filter: JSON: You can filter a list of endpoints by specifying one or several parameters:

  • creation_date: Exact endpoint creation date in ISO 8601 format
  • id: ID assigned to endpoint from the database
  • is_active:
  • last_modified: Exact date of the last endpoint modification in ISO 8601 format
  • meta: JSON that contains the data for reaching an endpoint
  • triggers: ID assigned to a trigger that activates notifications
  • type: The parameter sorts the endpoints by type (WI = WebInterface, EM = Email, WH = Webhook)
  • workspace: Workspace ID
  • workspace_id: Workspace ID

ids: [ID]: To get a list with certain endpoints, specify their IDs in the list.

limit: Int: The parameter allows to get the first n profiles from the list.

offset: Int: The parameter allows to remove the first n profiles from the list.

order: [String]:

withArchived: WithArchived: To get all endpoints including the archived ones, specify all. To get only archived endpoints, specify archived.

EndpointCollection!:Query result is a list of endpoints that contains the following parameters:

  • totalCount: Number of returned endpoints
  • profiles: [EndpointOutput!]!:
    • id: ID!: Endpoint ID
    • type: EndpointType!: Endpoint type can have the following values: Email, Webhook or WebInterface
    • meta: JSONString!: Endpoint meta-information for reaching this endpoint
    • lastModified: DateTime!: Last endpoint modification date in ISO 8601 format
    • creationDate: DateTime!: Endpoint creation date in ISO 8601 format
    • defaultAlias: DefaultAlias:
      • OWNER_EMAIL
      • WEB_INTERFACE
    • archived: Boolean!: Attribute that the endpoint is archived.

Example Request:

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

Example Response:

API returns the following result:
{
"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"
}
]
}
}
}

Create an Email Endpoint

Mutation createEmailEndpoint() allows to create a new endpoint of Email type.

createEmailEndpoint(endpointData: EmailEndpointInput!): EndpointManageOutput!

endpointData: EmailEndpointInput!: JSON with the information required for creating an endpoint:

  • targetEmail: String!: Email where notifications will be sent to.

EndpointManageOutput!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean!: Attribute that mutation is successfully completed
  • endpoint: EndpointOutput!: New endpoint object

Example Request:

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

Example Response:

API returns the following result:
{
"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"
}
}
}
}

Create a Webhook Endpoint

Mutation createWebhookEndpoint() allows to create a new endpoint of Webhook type.

createWebhookEndpoint(endpointData: WebhookEndpointInput!): EndpointManageOutput!

endpointData: WebhookEndpointInput!: JSON with the information required for creating an endpoint:

  • url: String!: URL where requests will be sent to
  • requestMethod: String!: Request method

EndpointManageOutput!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean!: Attribute that mutation is successfully completed
  • endpoint: EndpointOutput!: New endpoint object

Example Request:

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

Example Response:

API returns the following result:
{
"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"
}
}
}
}

Update an Endpoint

Mutation updateEndpoint() allows to update the endpoint information.

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

endpointId: ID!: Endpoint ID

endpointInfo: JSON: JSON-object with parameters to be updated. These parameters are similar to the parameters from meta: JSON

EndpointManageOutput!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean!: Attribute that mutation is successfully completed
  • endpoint: EndpointOutput!: Updated endpoint object

Incorrect input errors:

  • Endpoint not found by transmitted id:
{
"message": "Endpoint matching query does not exist."
}

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"updateEndpoint": {
"ok": true,
"endpoint": {
"id": "6fd67f81-a195-442b-a991-1a0eca6bbb69",
"meta": "{\"target_email\": \"new-email@test.com\", \"default_alias\": \"owner_email\"}"
}
}
}
}

Delete an Endpoint

Mutation deleteEndpoint() is used to archive a list of endpoints.

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

endpointIds: [String!]!: List of endpoint IDs

MutationResult!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean!: Attribute that mutation is successfully completed

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"deleteEndpoint": {
"ok": true
}
}
}

Triggers

Get Triggers

Query triggers allows to get a list of triggers for creating notifications. Triggers are related to the endpoints where notifications will be sent to.

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: You can filter a list of triggers by specifying one or several endpoints:

  • creation_date: Exact trigger creation date in ISO 8601 format
  • endpoints: Linked endpoint ID
  • id: ID assigned to a trigger from the database
  • is_active:
  • last_modified: Exact date of the last trigger modification in ISO 8601 format
  • meta:
  • workspace: Workspace ID
  • workspace_id: Workspace ID

ids: [ID]: To get a list of certain triggers, specify their IDs in the list.

limit: Int: The parameter allows to get the first n triggers from the list.

offset: Int: The parameter allows to remove the first n triggers from the list.

order: [String]: You can sort a list by specifying the value for the following parameters: creation_date, endpoints, id, is_active, last_modified, meta, workspace, workspace_id

targetId: ID: ID assigned to a group which the trigger is linked to

withArchived: WithArchived: To get all triggers, including the archived ones, specify all. To get only archived triggers, specify archived.

TriggerCollection!: The query result is a list of triggers that contains the following parameters:

  • totalCount: Int: Number of returned triggers
  • collectionItems: [TriggerType!]!:
    • id: ID!: Trigger ID
    • creationDate: DateTime!: Trigger creation date in ISO 8601 format
    • lastModified: DateTime!: Last trigger modification date in ISO 8601 format
    • meta: Meta!: Trigger meta-information
    • endpoints: [EndpointOutput!]!: List of endpoints linked to a trigger
    • archived: Boolean!: Attribute that a trigger is archived.

Example Request:

{
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
}
}
}

Example Response:

API returns the following result:
{
"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
}
]
}
}
}

Create a Trigger for a Profile Group

Mutation createProfileGroupTrigger allows to create a new trigger for a profile group. Everytime the camera detects a person from this group, the system creates a notification.

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

endpointAliases: [DefaultAlias!]: You can submit OWNER_EMAIL or WEB_INTERFACE. In this case one of endpoints with the same value for parameter defaultAlias will be linked to a trigger.

endpointIds: [ID!]: You can submit a list of IDs assigned to endpoints which are linked to a trigger.

endpointUrl: String: You can submit URL to your webhook. This will create a new endpoint for sending notifications to your URL address.

profileGroupId: ID!: Group ID necessary for creating a trigger.

TriggerManageOutput!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean!: Attribute that mutation is successfully completed
  • trigger: TriggerType!: New trigger object

Incorrect input errors:

  • Profile group not found by transmitted id:
{
"message": "Label matching query does not exist."
}
  • Endpoint not found by transmitted id:
{
"message": "Endpoint does not exist."
}

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"createProfileGroupTrigger": {
"trigger": {
"endpoints": [
{
"id": "afd7c121-3140-4a8c-b0ee-3717581eb76d"
}
],
"id": "9675aede-3ee8-495b-ac8b-e284a07db99e"
}
}
}
}

Update a Trigger

Mutation updateTrigger allows to update endpoints linked to a trigger. List of linked endpoints is replaced by the new one.

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

endpointAliases: [DefaultAlias!]: You can submit OWNER_EMAIL or WEB_INTERFACE. In this case one of endpoints with the same value in parameter defaultAlias will be linked to a trigger.

endpointIds: [ID!]: You can submit a list of IDs assigned to endpoints which will be linked to a trigger.

triggerId: ID!: Trigger ID

TriggerManageOutput!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean!: Attribute that mutation is successfully completed
  • trigger: TriggerType!: Updated trigger object

Incorrect input errors:

  • Trigger not found by passed id:
{
"message": "Trigger matching query does not exist."
}
  • Endpoint not found by transmitted id:
{
"message": "Endpoint does not exist."
}

Example Request:

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

Example Response:

API returns the following result:
{
"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"
}
]
}
}
}
}

Mutation linkEndpoint allows to link endpoint to trigger. The endpoint is to be added to a list of endpoints linked to the trigger.

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

endpointAliases: [DefaultAlias!]: You can submit OWNER_EMAIL or WEB_INTERFACE. In this case one of endpoints with the same value for parameter defaultAlias will be linked to a trigger.

endpointIds: ID!: You can submit ID assigned to an endpoint that will be linked to a trigger.

triggerId: ID!: Trigger ID

MutationResult!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean!: Attribute that mutation is successfully completed

Incorrect input errors:

  • Endpoint id for binding to a trigger has not been passed:
{
"message": "Unknown exception code for 'bad_input_data' type",
"code": "No id or alias provided"
}
  • Endpoint not found by transmitted id:
{
"message": "Endpoint matching query does not exist."
}
  • Trigger not found by passed id:
{
"message": "Trigger matching query does not exist."
}

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"linkEndpoint": {
"ok": true
}
}
}

Mutation unlinkEndpoint is used to unlink endpoint from trigger. The endpoint is removed from a list of endpoints linked to the trigger.

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

endpointAliases: [DefaultAlias!]: You can submit OWNER_EMAIL or WEB_INTERFACE. In this case one of endpoints with the same value for parameter defaultAlias is removed from a list of endpoints linked to this trigger.

endpointIds: ID!: You can submit ID of an endpoint to be removed from a list of endpoints linked to this trigger.

triggerId: ID!: Trigger ID

MutationResult!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean!: Attribute that mutation is successfully completed.

Incorrect input errors:

  • Endpoint id to unlink from the trigger has not been passed:
{
"message": "Unknown exception code for 'bad_input_data' type",
"code": "No id or alias provided"
}
  • Endpoint not found by transmitted id:
{
"message": "Endpoint matching query does not exist."
}
  • Trigger not found by passed id:
{
"message": "Trigger matching query does not exist."
}

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"unlinkEndpoint": {
"ok": true
}
}
}

Delete a Trigger

Mutation deleteTrigger allows to delete a trigger.

deleteTrigger(triggerId: ID!): MutationResult!

triggerId: ID!: Trigger ID

MutationResult!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean!: Attribute that mutation is successfully completed.

Incorrect input errors:

  • Trigger not found by passed id:
{
"message": "Trigger matching query does not exist."
}

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"deleteTrigger": {
"ok": true
}
}
}

Notifications

Get Notifications

Query notifications is used to get a list of notifications sent from the system.

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

filters: NotificationFilter: To get only required notifications, you can adjust filtration

  • id: Filtration by notification IDs:
    • exact: ID: Get an exact notification object using ID notification value.
    • iExact: ID: Get an exact notification object using ID notification value. Not case-sensitive.
    • contains: String: Get notification objects using value matching with notification ID.
    • iContains: String: Get notification objects using value matching with notification ID. Not case-sensitive.
    • inList: [ID!]: Get exact notification objects using a list of notification IDs.
    • gt: ID: Get notification objects which IDs are greater(>) than submitted IDs. String matching is used.
    • gte: ID: Get notification objects which IDs are greater than or equal to (>=) submitted ID. String matching is used.
    • lt: ID: Get notification objects which IDs are less (<) than submitted ID. String matching is used.
    • lte: ID: Get notification objects which IDs are less than or equal to(<=) submitted ID. String matching is used.
    • startsWith: String: Get notification objects which IDs start with submitted value.
    • iStartsWith: String: Get notification objects which IDs start with submitted value. Not case-sensitive.
    • endsWith: String: Get notification objects which IDs end with submitted value.
    • iEndsWith: String: Get notification objects which IDs end with submitted value. Not case-sensitive.
    • range: [ID!]: Get notification objects which IDs are within the range of submitted IDs. String matching is used.
    • isNull: Boolean: Get notification objects which IDs are equal(true) or not equal(false) to null.
    • regex: String: Get notification objects which IDs meet a submitted regular expression.
    • iRegex: String: Get notification objects which IDs meet a submitted regular expression. Not case-sensitive.
  • creationDate: DatetimeFilterLookupCustom: Filtration by notification creation date. The parameters are similar to the ones for filtration by ID.
  • lastModified: DatetimeFilterLookupCustom: Filtration by date of the last notification modification. The parameters are similar to the ones for filtration by ID.
  • isViewed: Boolean: Filtration of viewed (true) and not viewed (false) notifications.
  • isActive: Boolean: Filtration of active (true) and not active (false) notifications.
  • endpointId: UUID: Filtration of notifications by ID assigned to the endpoint they were sent to.
  • isSent: Boolean: Filtration of notifications by in-system notifications (true) and notifications sent to external endpoints (false).
  • triggerId: ID: Filtration of notifications by trigger ID.
  • profileId: ID: Filtration of notifications by profile ID.
  • type: NotificationType: Filtration of notifications by type.
  • profileGroupTitle: String: Filtration of notifications by group name.

order: NotificationOrdering: You can adjust sorting of notification list:

  • id: Ordering: Sorting by ID. String matching is used.(ASC: Ascending sorting, DESC: Descending sorting)
  • creationDate: Ordering: Sorting by notification creation date.
  • lastModified: Ordering: Sorting by date of the last notification modification.

pagination: OffsetPaginationInput:

  • limit: Int!: This parameter allows to get the first n notifications from the list.
  • offset: Int!: This parameter allows to remove the first n notifications from the list.

NotificationOutputCountList!: The query result is a list of notifications that contains the following parameters:

  • totalCount: Int!: Total number of notifications.
  • collectionItems: [NotificationOutput!]!:
    • id: ID!: Notification ID.
    • isActive: Boolean!: Attribute that notification is active.
    • isViewed: Boolean!: Attribute that notification is viewed.
    • lastModified: DateTime: Date of the last notification modification in ISO 8601 format.
    • activityId: ID: ID assigned to activity that causes creating of notification.
    • avatarId: ID: Profile avatar ID.
    • cameraId: ID: ID assigned to a camera that detected the activity.
    • cameraTitle: String: Camera name
    • creationDate: DateTime!: Notification creation date in ISO 8601 format.
    • currentCount: Int: Number of persons in the camera's field of view
    • description: String: Profile description
    • endpointStatuses: [EndpointStatusOutput!]: List of endpoints and their statuses:
      • endpoint: EndpointOutput!: Endpoint object.
      • status: String!: Submission status.
    • limit: Int: Max number of persons.
    • name: String: Profile name.
    • profileGroupColor: String: Color of the group linked to a trigger.
    • profileGroupId: ID: ID assigned to the group linked to a trigger.
    • profileGroupTitle: String: Name of the group linked to a trigger.
    • profileId: ID: Profile ID.
    • realtimeBodyPhotoId: String: ID assigned to a photo of the person detected by camera (Missing, if the anonymous mode is enabled).
    • realtimeFacePhotoId: String: ID assigned to a face image of a person detected by camera (Missing, if the anonymous mode is enabled).
    • triggerId: ID: ID assigned to a trigger that caused the notification.
    • type: String!: Notification type.

Example Request:

{
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
}
}
}

Example Response:

API returns the following result:
{
"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 <ShortProductName/> 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"
}
]
}
}
}

View Notifications

Mutation viewingNotifications marks one or several notifications as viewed.

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

notificationIds: [String!]!: List of IDs assigned to notifications which should be marked as viewed.

MutationResult:The mutation result is JSON that contains the following parameters:

  • ok: Boolean!: Attribute that mutation is successfully completed.

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"viewingNotifications": {
"ok": true
}
}
}

View All Notifications

Mutation markAllNotificationsAsViewed marks all notifications as viewed.

markAllNotificationsAsViewed: MutationResult!

MutationResult:The mutation result is JSON that contains the following parameters:

  • ok: Boolean!: Attribute that mutation is successfully completed.

Example Request:

mutation{
markAllNotificationsAsViewed {
ok
}
}

Example Response:

API returns the following result:
{
"data": {
"markAllNotificationsAsViewed": {
"ok": true
}
}
}

Activities

Get Activities

Query activities allows to get a list of activities detected by the camera.

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

filters: ActivityFilter: To get only required activities, you can adjust filtration

  • id: Filtration by activity ID:
    • exact: ID: Get an exact activity object using the value of activity ID.
    • iExact: ID: Get an exact activity object using the value of activity ID. Not case-sensitive.
    • contains: String: Get activity objects using the value matching with activity ID.
    • iContains: String: Get activity objects using the value matching with activity ID. Not case-sensitive.
    • inList: [ID!]: Get certain activity objects using a list of activity IDs.
    • gt: ID: Get activity objects which IDs are greater (>) than submitted ID. String matching is used.
    • gte: ID: Get activity objects which IDs are greater than or equal to (>=) to submitted ID. String matching is used.
    • lt: ID: Get activity objects which IDs are less (<) than submitted ID. String matching is used.
    • lte: ID: Get activity objects which IDs are less than or equal to (<=) to submitted ID. String matching is used.
    • startsWith: String: Get activity objects which IDs start with submitted value.
    • iStartsWith: String: Get activity objects which IDs start with submitted value. Not case-sensitive.
    • endsWith: String: Get activity objects which IDs end with submitted value.
    • iEndsWith: String: Get activity objects which IDs end with submitted value. Not case-sensitive.
    • range: [ID!]: Get activity objects which IDs are within the range of submitted IDs. String matching is used.
    • isNull: Boolean: Get activity objects which IDs are equal(true) or not equal to(false) null.
    • regex: String: Get activity objects which IDs meet a submitted regular expression.
    • iRegex: String: Get activity objects which IDs meet a submitted regular expression. Not case-sensitive.
  • creationDate: DatetimeFilterLookupCustom: Filtration by activity creation date. The parameters are similar to the ones for filtration by ID.
  • lastModified: DatetimeFilterLookupCustom: Filtration by date of the last activity modification. The parameters are similar to the ones for filtration by ID.
  • profileId: ID: Activity filtration by profile ID.

order: ActivityOrdering: You can adjust sorting of activity list:

  • id: Ordering: Sorting by ID. String matching is used.(ASC: Ascending sorting, DESC: Descending sorting)
  • creationDate: Ordering: Sorting by activity creation date.
  • lastModified: Ordering: Sorting by date of the last activity modification.

pagination: OffsetPaginationInput:

  • limit: Int!: The parameter allows to get the first n activities from the list.
  • offset: Int!: The parameter allows to remove the first n activities from the list.

ActivityOutputCountList!: The query result is an activity list that contains the following parameters:

  • totalCount: Int!: Number of returned activities.
  • collectionItems: [ActivityOutput!]!:
    • id: ID!: Activity ID.
    • data: JSON: Additional information about activity.
    • lastModified: DateTime: Date of the last activity modification in ISO 8601 format.
    • creationDate: DateTime!: Activity creation date in ISO 8601 format.
    • bestShotId: ID: ID of the best face image received from the camera that detected the activity (Missing, if the anonymous mode is enabled or the camera couldn't detect a face image).
    • cameraId: ID!: ID assigned to the camera that detected the activity.
    • locationId: String!: ID assigned to location which the camera is linked to.
    • profileId: ID: Profile ID.
    • status: ActivityType!:
      • Progress
      • Finalized
      • Failed
    • timeStart: String!: Activity starting time.
    • timeEnd: String!: Activity ending time.

Example Request:

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

Example Response:

API returns the following result:
{
"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"
}
]
}
}
}

Create a Profile by Activity

Mutation createProfileByActivity is used to create a profile using a detected activity.

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

activityId: ID!: ID assigned to the activity upon which a profile should be created.

profileData: ProfileInput: You can specify the additional information to be saved at profile:

  • profileGroupIds: [ID]: List of IDs assigned to the groups which the new profile is linked to.
  • info: JSON: Additional information about profile (age: Int, gender: "MALE" | "FEMALE")

ProfileCreateOutput:The mutation result is JSON that contains the following parameters:

  • ok: Boolean!: Attribute that mutation is successfully completed.
  • profile: ProfileOutput!: New profile object.
  • isCreated: Boolean!: Determines if a new profile is created or a photo was linked to the existing profile.

Incorrect input errors:

  • Error when trying to create a profile from an anonymous activity:
{
"message": "Activity is anonymous",
"code": "0x358vri3s"
}
  • Activity not found by passed id:
{
"message": "Activity matching query does not exist."
}
  • Profile groups not found by passed ids:
{
"message": "One or several profiles_groups does not exist",
"code": "0x573bkd35"
}

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"createProfileByActivity": {
"ok": true,
"isCreated": false,
"profile": {
"id": "1cf13933-00be-4a6d-8dc3-3ff17f94aef8"
}
}
}
}

Agents

Get Agents

Query agents allows to get a list of agents.

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

filter: JSON: You can filter a list of agents by specifying one or several parameters:

  • activations:
  • cameras: ID assigned to a camera stored in the database
  • creation_date: Exact agent creation date in ISO 8601 format
  • id: ID assigned to an agent stored in the database.
  • info__title: Agent name.
  • is_active: Agent activity attribute.
  • last_modified: Exact date of the last agent modification in ISO 8601 format
  • workspace: Workspace ID
  • workspace_id: Workspace ID

ids: [ID]: To get a list of certain agents, specify their IDs in the list.

limit: Int: The parameter allows to get the first n agents from the list.

offset: Int: The parameter allows to remove the first n agents from the list.

order: [String]: You can sort the list by specifying one of the values for the following parameters: activations, cameras, creation_date, id, info, is_active, last_modified, workspace, workspace_id.

withArchived: WithArchived: To get all agents, including the archived ones, specify all. To get only archived agents, specify archived.

AgentsCollection!: The query result is a list of agents that contains the following parameters:

  • totalCount: Int: Number of returned agents
  • collectionItems: [AgentsCollection!]!:
    • id: ID!: Agent ID
    • creationDate: DateTime!: Agent creation date in ISO 8601 format.
    • lastModified: DateTime!: Last agent modification date in ISO 8601 format.
    • token: String!: Agent's token
    • camerasIds: [ID!]: List of IDs assigned to cameras connected to an agent.
    • title: String: Agent name
    • agentStatus: String!: Agent status
    • agentLastActiveTime: String: Last activity date recorded by agent's camera.
    • archived: Boolean!: Agent archivation attribute.

Example Request:

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

Example Response:

API returns the following result:
{
"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"
}
]
}
}
}

Create an Agent

Mutation createAgent allows to create a new agent.

createAgent(agentData: AgentInput!): AgentCreateOutput!

agentData: AgentInput!: Information required for creating an agent:

  • title: String: Agent name.
  • extra: JSON: Additional information about agent.

AgentCreateOutput: The mutation result is JSON that contains the following parameters:

  • ok: Boolean!: Attribute that mutation is successfully completed.
  • agent: AgentOutput!: New agent object.
  • channelCost: String: Monthly service charge.
  • writeoffDate: String: Date of the next service in ISO 8601 format.

Incorrect input errors:

  • Error when creating a new agent because the limit has been exceeded:
{
"message": "Agent limit exceeded",
"code": "0x6245cd00"
}
  • Incorrect extra transmitted:
{
"message": "'int' object has no attribute 'get'"
}

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"createAgent": {
"ok": true,
"agent": {
"id": "2b769e5a-a49a-46ac-ac38-ec924bd4ec83"
}
}
}
}

Update an Agent

Mutation updateAgent is used to update information about agent.

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

agentData: AgentUpdateInput!: Information necessary for updating an agent:

  • title: String: Agent name.

agentId: ID!: ID assigned to the agent to be updated.

AgentManageOutput: The mutation result is JSON that contains the following parameters:

  • ok: Boolean!: Attribute that mutation is successfully completed.
  • agent: AgentOutput!: Updated agent object.

Incorrect input errors:

  • Agent not found by the transmitted id:
{
"message": "Camera matching query does not exist."
}

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"updateAgent": {
"ok": true,
"agent": {
"id": "19df2b38-7d23-44a5-85e7-c5a29b304581",
"title": "My old agent"
}
}
}
}

Delete an Agent

Mutation deleteAgent allows to delete one or several agents.

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

agentId: ID: ID assigned to an agent to be deleted.

agentIds: [ID!]: List of IDs assigned to agents to be deleted.

MutationResult!: The mutation result is JSON that contains the following parameters:

  • ok: Boolean!: Attribute that mutation is successfully completed.

Incorrect input errors:

  • No id has been passed for agent deletion:
{
"message": "One of the parameters agentId or agentIds is required",
"code": "0xe509f74d"
}

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"deleteAgent": {
"ok": true
}
}
}

Others

Query analytics allows to get links to analytics.

analytics: AnalyticsOutput!

AnalyticsOutput!: The query result is a link list:

  • retail: String: Link to Crowd Analytics.
  • advertising: String: Link to Digital Signage

Example Request:

{
analytics {
advertising
retail
}
}

Example Response:

API returns the following result:
{
"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"
}
}
}

Get User Information

Query me allows to get information about authorized user.

me: UserType!

UserType!: The query result is a link list:

  • username: String!: User name.
  • email: String!: User email.
  • firstName: String!: User first name.
  • lastName: String!: User last name.
  • workspaces: [WorkspaceType!]!: Information about user's workspaces.

Example Request:

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

Example Response:

API returns the following result:
{
"data": {
"me": {
"email": "aa@aa.ru",
"firstName": "",
"lastName": "",
"username": "aa@aa.ru",
"workspaces": [
{
"id": "8d100a02-1b5b-4da1-b645-9fd01ef09c77"
}
]
}
}
}