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:
- Open GraphQL interactive console by clicking Platform API button at Resources widget of web interface.
- Copy the request below to the console and click Execute Query button.
query{
me {
workspaces {
accesses {
id
}
}
}
}
- As a result, GraphQL returns the response with a token (id):
{
"data": {
"me": {
"workspaces": [
{
"accesses ": [
{
"id": "3460***"
}
]
}
]
}
}
}
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
- qaa: Qaa! Quality assessment algorithm operates with the following data:
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": "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",
"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 IDcreationDate
: Sample creation date in ISO 8601 format with time zonelastModified
: Last sample modification date in ISO 8601 format with time zonedata
: 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
Profile Search
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.
Activity Search
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 formatid
: ID assigned to a profile from the databaseinfo
: Object with the following parameters:age
: Profile age. For example, a request with a parameterinfo_age:28
returns a list of profiles with age equal to 28.gender
: Profile gender. For example, a request with a parameterinfo_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 formatlink_to_label
:person
:person_id
: ID assigned to a profile from the databaseprofile_groups
: List of group IDssamples
: Sample IDworkspace
: Workspace IDworkspace_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 profilescollectionItems: [ProfileOutput!]
id
: Profile IDlastModified
: Last profile modification date in ISO 8601 formatcreationDate
: Profile creation date in ISO 8601 formatinfo
: Profile information (approximate age, gender, avatar ID, the best sample ID)samples
: List of profile samplesprofileGroups
: List of profile groupsmainSample
: The best profile sampleavatar
: Profile avataractivities
: All profile activitiesactivitiesCount
: Number of profile activitiesfirstActivityDate
: The first profile activity date recorded by the system in IS O8601 formatlastActivityDate
: 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 toinfo: 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 completedprofile: ProfileOutput!
: New profile objectisCreated: 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 completedprofile: 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 formatid
: ID assigned to a group from the databaseinfo
: JSON completely similar toinfo
parameter of a group objectlast_modified
: Exact date of the last group modification in ISO 8601 formatlink_to_profile
:profiles
: List of profile IDstitle
: Group nametype
:workspace
: Workspace IDworkspace_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 groupscollectionItems: [ProfileGroupOutput!]!
:id
: Group IDtitle
: Group nameinfo
: Additional group information in JSON formatlastModified
: Last group modification date in ISO 8601 formatcreationDate
: Group creation date in ISO 8601 formatprofileIds
: 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 nameinfo: JSON = null
: Additional group information
ProfileGroupInput!
: The mutation result is JSON with the following parameters:
ok: Boolean
: Flag that mutation is successfully completedprofileGroup: 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 nameinfo
: 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 completedprofileGroup: 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 completedprofiles: [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 completedprofiles: [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 formatid
: ID assigned to endpoint from the databaseis_active
:last_modified
: Exact date of the last endpoint modification in ISO 8601 formatmeta
: JSON that contains the data for reaching an endpointtriggers
: ID assigned to a trigger that activates notificationstype
: The parameter sorts the endpoints by type (WI = WebInterface
,EM = Email
,WH = Webhook
)workspace
: Workspace IDworkspace_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 endpointsprofiles: [EndpointOutput!]!
:id: ID!
: Endpoint IDtype: EndpointType!
: Endpoint type can have the following values:Email
,Webhook
orWebInterface
meta: JSONString!
: Endpoint meta-information for reaching this endpointlastModified: DateTime!
: Last endpoint modification date in ISO 8601 formatcreationDate: DateTime!
: Endpoint creation date in ISO 8601 formatdefaultAlias: 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 completedendpoint: 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 torequestMethod: String!
: Request method
EndpointManageOutput!
: The mutation result is JSON that contains the following parameters:
ok: Boolean!
: Attribute that mutation is successfully completedendpoint: 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 completedendpoint: 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 formatendpoints
: Linked endpoint IDid
: ID assigned to a trigger from the databaseis_active
:last_modified
: Exact date of the last trigger modification in ISO 8601 formatmeta
:workspace
: Workspace IDworkspace_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 triggerscollectionItems: [TriggerType!]!
:id: ID!
: Trigger IDcreationDate: DateTime!
: Trigger creation date in ISO 8601 formatlastModified: DateTime!
: Last trigger modification date in ISO 8601 formatmeta: Meta!
: Trigger meta-informationendpoints: [EndpointOutput!]!
: List of endpoints linked to a triggerarchived: 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 completedtrigger: 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 completedtrigger: 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"
}
]
}
}
}
}
Link an Endpoint to a Trigger
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
}
}
}
Unlink an Endpoint from a Trigger
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
) tonull
.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 firstn
notifications from the list.offset: Int!
: This parameter allows to remove the firstn
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 namecreationDate: DateTime!
: Notification creation date in ISO 8601 format.currentCount: Int
: Number of persons in the camera's field of viewdescription: String
: Profile descriptionendpointStatuses: [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 firstn
activities from the list.offset: Int!
: The parameter allows to remove the firstn
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 databasecreation_date
: Exact agent creation date in ISO 8601 formatid
: 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 formatworkspace
: Workspace IDworkspace_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 agentscollectionItems: [AgentsCollection!]!
:id: ID!
: Agent IDcreationDate: DateTime!
: Agent creation date in ISO 8601 format.lastModified: DateTime!
: Last agent modification date in ISO 8601 format.token: String!
: Agent's tokencamerasIds: [ID!]
: List of IDs assigned to cameras connected to an agent.title: String
: Agent nameagentStatus: String!
: Agent statusagentLastActiveTime: 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
Get Links to Analytics
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"
}
]
}
}
}