Introduction
Welcome to the SAIA MTM API Documentation! You can use Person API - to get measurements for a person.
Authentication
To authorize, use this code:
import requests
session = requests.Session()
session.headers.update({
'Authorization': "APIKey 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b"
})
session.get('https://saia.3dlook.me/api/v2/persons/')
# With shell, you can just pass the correct header with each request
curl "https://saia.3dlook.me/api/v2/persons/"
-H "Authorization: APIKey 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b"
var settings = {
"async": true,
"crossDomain": true,
"url": "https://saia.3dlook.me/api/v2/persons/",
"method": "GET",
"headers": {
"Authorization": "APIKey 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b",
},
"processData": false,
}
$.ajax(settings).done(function (response) {
});
Make sure to replace
9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
with your API key.
SAIA uses API keys to allow access to the API. Please check your API key in your Mobile Tailor admin panel.
For client authentication, include the token key in all API requests to the server in a header. The key should be prefixed by the string literal ""APIKey,"" with a whitespace separating the two strings. For example:
Authorization: APIKey 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
Correct Flow
To start body calculation parameters, you need to create a Person object. Complete Person with all required data for calculations, you can build it in TWO WAYS. It depends on your options to send base64 encoded photos:
Single Request
If it's ok for you to decode photos to Base64 format, you can:
- Create a Person in a single POST request;
- Then the tasks for calculating will automatically trigger and you will get a URL for tracking the status of tasks;
- Periodically check the status. When the tasks are finished successfully you will get a redirect to the person URL with the calculations;
Two Requests
If you want to send photos as files:
- Create a Person only with
gender
,height
andweight
POST request; - Update Previously created person using its Update method;
- Then the tasks for calculating will automatically trigger and you will get a URL for tracking the status of tasks;
- Periodically check the status. When the tasks are finished successfully you will get a redirect to the person URL with the calculations;
Correctly GET results
- while
"is_ready": false
periodically check status of task set - average period of check is 4 seconds
- if
"is_successful": false
and"is_ready": true
, you will get a cause of failure - when all tasks are finished you will be redirected (303) to the person with calculated params
Incorrect Photo
If you got an error on the calculation task of side or front photo, you can:
- Partial Update wrong photo on a previously created person;
- Manually run a calculation and you will get a URL for tracking status of tasks;
Soft Validation Parameters
Parameter | Validation | Description |
---|---|---|
legs_distance | > 28 | Distance between legs, in cm |
body_area_percentage | = 0.7 | Percentage of body on the photo |
Person Model
Create a New Person
import requests
headers = {
'Authorization': 'APIKey <YOUR_API_KEY_HERE>',
'Content-Type': 'application/json'
}
payload = {
'gender': 'female',
'height': 170,
'weight': 70.0
}
response = requests.request('POST', 'https://saia.3dlook.me/api/v2/persons/?measurements_type=all', data=payload, headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/persons/?measurements_type=all"
-X POST
-H "Authorization: APIKey <YOUR_API_KEY_HERE>"
-d '{
"gender": "female",
"height": 170,
"weight": 70.0
}'
var payload = {
"gender": "female",
"height": 170,
"weight": 70.0
}
var settings = {
"async": true,
"crossDomain": true,
"url": "https://saia.3dlook.me/api/v2/persons/?measurements_type=all",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Authorization": "APIKey <YOUR_API_KEY_HERE>",
},
"processData": false,
"data": JSON.stringify(payload)
}
$.ajax(settings).done(function (response) {
console.log(response);
});
The above command returns JSON structured like this:
{
"id": 3,
"url": "https://saia.3dlook.me/api/v2/persons/3/?measurements_type=all",
"gender": "female",
"height": 170,
"weight": 70.0
}
This endpoint creates a new person, with metadata first and then the partial update with front and side images, with all parameters with front image and side image Base64 encoded.
HTTP Request
POST https://saia.3dlook.me/api/v2/persons/?measurements_type=all
Request Body
The request body should be an "application/json"
encoded object, containing the following items.
Parameter | Type | Validation | Description |
---|---|---|---|
gender | string | required , male or female |
gender of person, male or female |
height | integer | required , >= 150 , <= 220 |
height of person, in cm |
weight | float | required , >= 30 , <= 200 |
weight of person, in kg |
Update a Specific Person
import requests
headers = {
'Authorization': 'APIKey <YOUR_API_KEY_HERE>',
'Content-Type': 'application/json'
}
files={
'front_image': open('path_to_file', 'rb'),
'side_image': open('path_to_file', 'rb'),
}
response = requests.request('PUT', 'https://saia.3dlook.me/api/v2/persons/3/?measurements_type=all', files=files, headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/persons/3/?measurements_type=all"
-X PUT
-H "Authorization: APIKey <YOUR_API_KEY_HERE>"
-F front_image=@/path/to/files/front_photo.jpg \
-F side_image=@/path/to/files/side_photo.jpg
var form = new FormData();
form.append("front_image", $('your-input[type=file]')[0].files[0]);
form.append("side_image", $('your-input[type=file]')[0].files[0]);
var settings = {
"async": true,
"crossDomain": true,
"url": "https://saia.3dlook.me/api/v2/persons/3/?measurements_type=all",
"method": "PUT",
"headers": {
"Authorization": "APIKey <YOUR_API_KEY_HERE>",
},
"processData": false,
"contentType": false,
"mimeType": "multipart/form-data",
"data": form
}
$.ajax(settings).done(function (response) {
console.log(response);
});
The above command returns JSON structured like this:
{
"task_set_url": "https://saia.3dlook.me/api/v2/queue/4d563d3f-38ae-4b51-8eab-2b78483b153e/"
}
Response also contains header:
"Location": "https://saia.3dlook.me/api/v2/queue/4d563d3f-38ae-4b51-8eab-2b78483b153e/"
This endpoint uploads front and side images to a new person, if you are not able to send photos in Base64 encoding.
HTTP Request
PUT https://saia.3dlook.me/api/v2/persons/<id>/?measurements_type=all
URL Parameters
The following parameters should be included in the URL path.
Parameter | Description |
---|---|
id | The ID of the person created without front and side photo |
Request Body
The request body should be a "multipart/form-data"
encoded object, containing the following items.
Parameter | Type | Validation | Description |
---|---|---|---|
front_image | file | correct image, filename with image extension |
front photo of person |
side_image | file | correct image, filename with image extension |
side photo of person |
Create a New Person Single request
import requests
headers = {
'Authorization': 'APIKey <YOUR_API_KEY_HERE>',
'Content-Type': 'application/json'
}
payload = {
'gender': 'female',
'height': 170,
'weight': 70.0,
'front_image': 'base64_decoded_image',
'side_image': 'base64_decoded_image'
}
response = requests.request('POST', 'https://saia.3dlook.me/api/v2/persons/?measurements_type=all', data=payload, headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/persons/?measurements_type=all"
-X POST
-H "Authorization: APIKey <YOUR_API_KEY_HERE>"
-d '{
"gender": "female",
"height": 170,
"weight": 70.0,
"front_image": "base64_decoded_image",
"side_image": "base64_decoded_image"
}'
var payload = {
"gender": "female",
"height": 170,
"weight": 70.0,
"front_image": "base64_decoded_image",
"side_image": "base64_decoded_image"
}
var settings = {
"async": true,
"crossDomain": true,
"url": "https://saia.3dlook.me/api/v2/persons/?measurements_type=all",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Authorization": "APIKey <YOUR_API_KEY_HERE>",
},
"processData": false,
"data": JSON.stringify(payload)
}
$.ajax(settings).done(function (response) {
console.log(response);
});
The above command returns JSON structured like this:
{
"task_set_url": "https://saia.3dlook.me/api/v2/queue/4d563d3f-38ae-4b51-8eab-2b78483b153e/"
}
This endpoint creates a new person, with metadata first and then the partial update with front and side images, with all parameters with front image and side image Base64 encoded.
HTTP Request
POST https://saia.3dlook.me/api/v2/persons/?measurements_type=all
Request Body
The request body should be an "application/json"
encoded object, containing the following items.
Parameter | Type | Validation | Description |
---|---|---|---|
gender | string | required , male or female |
gender of person, male or female |
height | integer | required , >= 150 , <= 220 |
height of person, in cm |
weight | float | required , >= 30 , <= 200 |
weight of person, in kg |
front_image | string | image encoded to Base64 |
front photo of person |
side_image | string | image encoded to Base64 |
side photo of person |
Partial Update a Specific Person
import requests
headers = {
'Authorization': 'APIKey <YOUR_API_KEY_HERE>',
'Content-Type': 'application/json'
}
files={
'front_image': open('path_to_file', 'rb'),
'side_image': open('path_to_file', 'rb'),
}
response = requests.request('PATCH', 'https://saia.3dlook.me/api/v2/persons/3/', files=files, headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/persons/3/"
-X PATCH
-H "Authorization: APIKey <YOUR_API_KEY_HERE>"
-F front_image=@/path/to/files/front_photo.jpg \
-F side_image=@/path/to/files/side_photo.jpg
var form = new FormData();
form.append("front_image", $('your-input[type=file]')[0].files[0]);
form.append("side_image", $('your-input[type=file]')[0].files[0]);
var settings = {
"async": true,
"crossDomain": true,
"url": "https://saia.3dlook.me/api/v2/persons/3/",
"method": "PATCH",
"headers": {
"Authorization": "APIKey <YOUR_API_KEY_HERE>",
},
"processData": false,
"contentType": false,
"mimeType": "multipart/form-data",
"data": form
}
$.ajax(settings).done(function (response) {
console.log(response);
});
The above command returns JSON structured like this:
{
"front_image": "person/front_image_name.jpg",
"side_image": "person/side_image_name.jpg"
}
Response also contains header:
This endpoint is required for the partial update of side or front photos, in case where you want to rerun calculation due to the error.
HTTP Request
PATCH https://saia.3dlook.me/api/v2/persons/<id>/
URL Parameters
The following parameters should be included in the URL path.
Parameter | Description |
---|---|
id | The ID of the person created without front and side photo |
Request Body
The request body should be a "multipart/form-data"
encoded object, containing the following items.
Parameter | Type | Validation | Description |
---|---|---|---|
front_image | file | correct image, filename with image extension |
front photo of person |
side_image | file | correct image, filename with image extension |
side photo of person |
Get a Specific Person
import requests
headers = {
'Authorization': 'APIKey <YOUR_API_KEY_HERE>'
}
response = requests.request('GET', 'https://saia.3dlook.me/api/v2/persons/545/', headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/persons/545/"
-H "Authorization: APIKey <YOUR_API_KEY_HERE>"
var settings = {
"async": true,
"crossDomain": true,
"url": "https://saia.3dlook.me/api/v2/persons/545/",
"method": "GET",
"headers": {
"Authorization": "APIKey <YOUR_API_KEY_HERE>",
},
"processData": false,
}
$.ajax(settings).done(function (response) {
console.log(response);
});
The above command returns JSON structured like this:
{
"id": 114622,
"url": "https://saia.3dlook.me/api/v2/persons/114622/",
"gender": "male",
"height": 200,
"volume_params": {
"chest": 102.92,
"waist": 79.64,
"low_hips": 102.19,
"high_hips": 91.44,
"bicep": 32.63,
"knee": 39.76,
"ankle": 28.1,
"wrist": 19.09,
"calf": 40.2,
"thigh": 62.43,
"mid_thigh_girth": 52.88,
"neck": 40.7,
"forearm": 28.79,
"neck_girth": 38.46,
"neck_girth_relaxed": 34.38,
"under_bust_girth": 91.97,
"upper_chest_girth": 103.8,
"elbow_girth": 29.2,
"abdomen": 86.78,
"armscye_girth": 53.29
},
"front_params": {
"soft_validation": {
"messages": ""
},
"body_height": 53.77,
"outseam": 130.96,
"outseam_from_upper_hip_level": 96.04,
"inseam": 86.37,
"inside_crotch_length_to_mid_thigh": 45,
"inside_crotch_length_to_knee": 33,
"inside_crotch_length_to_calf": 23,
"crotch_length": 35.11,
"sleeve_length": 69.86,
"underarm_length": 45.61,
"legs_distance": 21.67,
"high_hips": 33.75,
"hip_height": 108.96,
"shoulders": 46.01,
"chest_top": 37.61,
"jacket_length": 78.15,
"shoulder_length": 13.94,
"neck": 14.71,
"waist": 29.94,
"waist_to_low_hips": 23.19,
"waist_to_knees": 70.88,
"nape_to_waist_centre_back": 51.39,
"bust_height": 149.63,
"shoulder_slope": 22.8,
"shoulder_to_waist": 47.69,
"side_neck_point_to_armpit": 22.46,
"back_neck_height": 173.1,
"back_neck_point_to_wrist_length": 93.55,
"upper_hip_height": 118.17,
"waist_height": 132.15,
"across_back_width": 41.43,
"outer_ankle_height": 10.66,
"knee_height": 61.27,
"across_back_shoulder_width": 47.57,
"total_crotch_length": 84.24,
"inside_leg_height": 97.04,
"neck_length": 10.1,
"upper_arm_length": 36.88,
"lower_arm_length": 32.98,
"upper_hip_to_hip_length": 9.21,
"back_shoulder_width": 50.67,
"rise": 27.69,
"back_neck_to_hip_length": 68.92,
"torso_height": 79.11,
"front_crotch_length": 36.14,
"back_crotch_length": 45.78
},
"side_params": {
"soft_validation": {
"messages": ""
},
"neck_to_chest": 26.21,
"chest_to_waist": 21.47,
"waist_to_ankle": 122.73,
"shoulders_to_knees": 115.7,
"side_upper_hip_level_to_knee": 59.38,
"side_neck_point_to_upper_hip": 56.28
}
}
This endpoint retrieves a specific person with calculated params after all calculation tasks were finished.
HTTP Request
GET https://saia.3dlook.me/api/v2/persons/<id>/
URL Parameters
The following parameters should be included in the URL path.
Parameter | Description |
---|---|
id | The ID of the person with calculations to retrieve |
List All Persons
import requests
headers = {
'Authorization': 'APIKey <YOUR_API_KEY_HERE>'
}
response = requests.request('GET', 'https://saia.3dlook.me/api/v2/persons/', headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/persons/"
-H "Authorization: APIKey <YOUR_API_KEY_HERE>"
var settings = {
"async": true,
"crossDomain": true,
"url": "https://saia.3dlook.me/api/v2/persons/",
"method": "GET",
"headers": {
"Authorization": "APIKey <YOUR_API_KEY_HERE>",
},
"processData": false,
}
$.ajax(settings).done(function (response) {
console.log(response);
});
The above command returns JSON structured like this:
{
"count": 20,
"next": "https://saia.3dlook.me/api/v2/persons/?page=2",
"previous": null,
"results": [
{
"id": 114622,
"url": "https://saia.3dlook.me/api/v2/persons/114622/",
"gender": "male",
"height": 200,
"volume_params": {
"chest": 102.92,
"waist": 79.64,
"low_hips": 102.19,
"high_hips": 91.44,
"bicep": 32.63,
"knee": 39.76,
"ankle": 28.1,
"wrist": 19.09,
"calf": 40.2,
"thigh": 62.43,
"mid_thigh_girth": 52.88,
"neck": 40.7,
"forearm": 28.79,
"neck_girth": 38.46,
"neck_girth_relaxed": 34.38,
"under_bust_girth": 91.97,
"upper_chest_girth": 103.8,
"elbow_girth": 29.2,
"abdomen": 86.78,
"armscye_girth": 53.29
},
"front_params": {
"soft_validation": {
"messages": ""
},
"body_height": 53.77,
"outseam": 130.96,
"outseam_from_upper_hip_level": 96.04,
"inseam": 86.37,
"inside_crotch_length_to_mid_thigh": 45,
"inside_crotch_length_to_knee": 33,
"inside_crotch_length_to_calf": 23,
"crotch_length": 35.11,
"sleeve_length": 69.86,
"underarm_length": 45.61,
"legs_distance": 21.67,
"high_hips": 33.75,
"hip_height": 108.96,
"shoulders": 46.01,
"chest_top": 37.61,
"jacket_length": 78.15,
"shoulder_length": 13.94,
"neck": 14.71,
"waist": 29.94,
"waist_to_low_hips": 23.19,
"waist_to_knees": 70.88,
"nape_to_waist_centre_back": 51.39,
"bust_height": 149.63,
"shoulder_slope": 22.8,
"shoulder_to_waist": 47.69,
"side_neck_point_to_armpit": 22.46,
"back_neck_height": 173.1,
"back_neck_point_to_wrist_length": 93.55,
"upper_hip_height": 118.17,
"waist_height": 132.15,
"across_back_width": 41.43,
"outer_ankle_height": 10.66,
"knee_height": 61.27,
"across_back_shoulder_width": 47.57,
"total_crotch_length": 84.24,
"inside_leg_height": 97.04,
"neck_length": 10.1,
"upper_arm_length": 36.88,
"lower_arm_length": 32.98,
"upper_hip_to_hip_length": 9.21,
"back_shoulder_width": 50.67,
"rise": 27.69,
"back_neck_to_hip_length": 68.92,
"torso_height": 79.11,
"front_crotch_length": 36.14,
"back_crotch_length": 45.78
},
"side_params": {
"soft_validation": {
"messages": ""
},
"neck_to_chest": 26.21,
"chest_to_waist": 21.47,
"waist_to_ankle": 122.73,
"shoulders_to_knees": 115.7,
"side_upper_hip_level_to_knee": 59.38,
"side_neck_point_to_upper_hip": 56.28
}
},
{
"id": 114623,
"url": "https://saia.3dlook.me/api/v2/persons/114623/",
"gender": "male",
"height": 200,
"volume_params": {
"chest": 102.92,
"waist": 79.64,
"low_hips": 102.19,
"high_hips": 91.44,
"bicep": 32.63,
"knee": 39.76,
"ankle": 28.1,
"wrist": 19.09,
"calf": 40.2,
"thigh": 62.43,
"mid_thigh_girth": 52.88,
"neck": 40.7,
"forearm": 28.79,
"neck_girth": 38.46,
"neck_girth_relaxed": 34.38,
"under_bust_girth": 91.97,
"upper_chest_girth": 103.8,
"elbow_girth": 29.2,
"abdomen": 86.78,
"armscye_girth": 53.29
},
"front_params": {
"soft_validation": {
"messages": ""
},
"body_height": 53.77,
"outseam": 130.96,
"outseam_from_upper_hip_level": 96.04,
"inseam": 86.37,
"inside_crotch_length_to_mid_thigh": 45,
"inside_crotch_length_to_knee": 33,
"inside_crotch_length_to_calf": 23,
"crotch_length": 35.11,
"sleeve_length": 69.86,
"underarm_length": 45.61,
"legs_distance": 21.67,
"high_hips": 33.75,
"hip_height": 108.96,
"shoulders": 46.01,
"chest_top": 37.61,
"jacket_length": 78.15,
"shoulder_length": 13.94,
"neck": 14.71,
"waist": 29.94,
"waist_to_low_hips": 23.19,
"waist_to_knees": 70.88,
"nape_to_waist_centre_back": 51.39,
"bust_height": 149.63,
"shoulder_slope": 22.8,
"shoulder_to_waist": 47.69,
"side_neck_point_to_armpit": 22.46,
"back_neck_height": 173.1,
"back_neck_point_to_wrist_length": 93.55,
"upper_hip_height": 118.17,
"waist_height": 132.15,
"across_back_width": 41.43,
"outer_ankle_height": 10.66,
"knee_height": 61.27,
"across_back_shoulder_width": 47.57,
"total_crotch_length": 84.24,
"inside_leg_height": 97.04,
"neck_length": 10.1,
"upper_arm_length": 36.88,
"lower_arm_length": 32.98,
"upper_hip_to_hip_length": 9.21,
"back_shoulder_width": 50.67,
"rise": 27.69,
"back_neck_to_hip_length": 68.92,
"torso_height": 79.11,
"front_crotch_length": 36.14,
"back_crotch_length": 45.78
},
"side_params": {
"soft_validation": {
"messages": ""
},
"neck_to_chest": 26.21,
"chest_to_waist": 21.47,
"waist_to_ankle": 122.73,
"shoulders_to_knees": 115.7,
"side_upper_hip_level_to_knee": 59.38,
"side_neck_point_to_upper_hip": 56.28
}
}
]
}
This endpoint retrieves all your existing persons with calculations.
HTTP Request
GET https://saia.3dlook.me/api/v2/persons/
Query Parameters
The following parameters should be included as part of the URL query string.
Parameter | Default | Description |
---|---|---|
page | A page number within the paginated result set. |
Manually Start Calculations of a Specific Person
import requests
headers = {
'Authorization': 'APIKey <YOUR_API_KEY_HERE>'
}
response = requests.request('GET', 'https://saia.3dlook.me/api/v2/persons/545/calculate/?measurements_type=all', headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/persons/545/calculate/?measurements_type=all"
-H "Authorization: APIKey <YOUR_API_KEY_HERE>"
var settings = {
"async": true,
"crossDomain": true,
"url": "https://saia.3dlook.me/api/v2/persons/545/calculate/?measurements_type=all",
"method": "GET",
"headers": {
"Authorization": "APIKey <YOUR_API_KEY_HERE>",
},
"processData": false,
}
$.ajax(settings).done(function (response) {
console.log(response);
});
The above command returns JSON structured like this:
{
"task_set_url": "https://saia.3dlook.me/api/v2/queue/4d563d3f-38ae-4b51-8eab-2b78483b153e/"
}
This endpoint is manually run calculations of all parameters after Partial Update of photos of a specific person. As a result, you will get URL for task_set, where the info can be tracked.
HTTP Request
GET https://saia.3dlook.me/api/v2/persons/<id>/calculate/?measurements_type=all
URL Parameters
The following parameters should be included in the URL path.
Parameter | Description |
---|---|
id | The ID of the person with calculations to retrieve |
Get a Specific Task Set
import requests
headers = {
'Authorization': "APIKey <YOUR_API_KEY_HERE>"
}
response = requests.request('GET', 'https://saia.3dlook.me/api/v2/queue/6a885ee2-153a-4cc4-9111-fbee31738410/', headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/queue/6a885ee2-153a-4cc4-9111-fbee31738410/"
-H "Authorization: APIKey <YOUR_API_KEY_HERE>"
var settings = {
"async": true,
"crossDomain": true,
"url": "https://saia.3dlook.me/api/v2/queue/6a885ee2-153a-4cc4-9111-fbee31738410/",
"method": "GET",
"headers": {
"Authorization": "APIKey <YOUR_API_KEY_HERE>",
},
"processData": false,
}
$.ajax(settings).done(function (response) {
console.log(response);
});
The above command returns JSON structured like this:
{
"is_successful": false,
"is_ready": false,
"sub_tasks": [
{
"name": "unrecognized_task",
"status": "PENDING",
"task_id": "6bbe7942-eadd-4bd2-84c8-c03f9c6a2f7a",
"message": ""
},
{
"name": "unrecognized_task",
"status": "PENDING",
"task_id": "10324eb8-c60f-4b20-baed-9c66d9ca9e66",
"message": ""
},
{
"name": "unrecognized_task",
"status": "PENDING",
"task_id": "10324eb8-c60f-4b20-baed-9c66d9ca9e66",
"message": ""
}
]
}
Returns information of given task-set:
- while its
is_ready
equalsFalse
, we can track task statuses. - when its
is_successful
equalsFalse
andis_ready
equalsTrue
, you will see the reason, why the task is unsuccessful. - when
is_successful
equalsTrue
andis_ready
equalsTrue
, API response 303 redirects to the target person resource.
HTTP Request
GET https://saia.3dlook.me/api/v2/queue/<task_set_id>/
URL Parameters
Parameter | Description |
---|---|
task_set_id | The id of the task_set to retrieve |
Integration
Javascript SDK for SAIA MTM API
Errors
HTTP Errors
The SAIA API uses the following error codes:
Error Code | Meaning |
---|---|
400 | Bad Request -- Your request is invalid. |
401 | Unauthorized -- Your API key is incorrect. |
403 | Forbidden -- Access to the requested API is forbidden. |
404 | Not Found -- The specified item could not be found. |
406 | Not Acceptable -- You requested a non-JSON format. |
422 | Unprocessable Entity -- One or both of the taken photos could not be processed. |
429 | Too Many Requests -- You are sending too many requests. |
500 | Internal Server Error -- A server error occurred. Try again later. |
503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |
Task Errors
Asynс Params Calculation Tasks uses the following error codes:
Application Code | Message | Meaning |
---|---|---|
900 | The pose is wrong, check your <body_part> |
The pose of the human body in one or both of the taken photos is wrong and we cannot process the human body. |
901 | Сan not detect the human body |
The human body in the photo cannot be detected. |
903 | Side photo in the front |
The photo taken to the Front slot was detected to be a Side photo. |
904 | The body is not full |
The photo does not contain the whole body. |
Soft Validation Errors
Each returned person's JSON could include objects(for Front and Side photos) with recommendation message for users how they can get more accurate calculation results(Soft validation):
Application Code | Message | Meaning |
---|---|---|
920 | Keep your head straight |
Head tilt detected. |
921 | Keep your hands at waist level |
Hand placement detected at hips or chest levels. |
922 | Check your <body_part> |
Minor problem(s) detected with one or multiple body part(s). |
923 | Selfie pose |
Minor detected that photo was made with selfie. |
How-To
Step-by-step guides for your use cases
Basic SDK flow example
<label for="front_image">
<input type="file" name="front_image" id="front_image">
</label>
Choose front image:
<label for="side_image">
<input type="file" name="side_image" id="side_image">
</label>
Choose side image:
<label for="gender">
<select name="gender" id="gender">
<option value="male">male</option>
<option value="female">female</option>
</select>
</label>
Choose gender:
<label for="height">
<input type="number" name="height" id="height" value="170">
</label>
<p>Execution status: <span id="status"></span></p>
<button id="start" type="button">START</button>
<pre id="results" class="results"></pre>
Enter height:
<label for="weight">
<input type="number" name="weight" id="weight" value="80">
</label>
<p>Execution status: <span id="status"></span></p>
<button id="start" type="button">START</button>
<pre id="results" class="results"></pre>
Enter weight:
import SAIA from ‘@3dlook/saia-sdk’;
const frontImage = document.getElementById('front_image');
const sideImage = document.getElementById('side_image');
const gender = document.getElementById('gender');
const height = document.getElementById('height');
const startBtn = document.getElementById('start');
const results = document.getElementById('results');
const status = document.getElementById('status');
const saia = new SAIA({
key: '<YOUR_API_KEY>',
});
Import SAIA SDK class:
startBtn.addEventListener('click', () => {
let frontImage64;
let sideImage64;
// convert front image to base64
saia.utils.getBase64(frontImage.files[0])
.then((base64) => {
frontImage64 = base64;
// convert side image to base64
return saia.utils.getBase64(sideImage.files[0]);
})
.then((base64) => {
sideImage64 = base64;
// create person with gender, height and images
return saia.api.person.create({
gender: gender.value,
height: height.value,
frontImage: frontImage64,
sideImage: sideImage64,
});
})
.then((taskSetId) => {
status.innerHTML = 'Processing...';
// check person processing and get the result
return saia.api.queue.getResults(taskSetId);
})
.then((person) => {
status.innerHTML = 'Finished';
// print the result out
results.innerHTML = JSON.stringify(person, null, ' ');
})
.catch((e) => {
console.log(e);
});
});
Set the start button click event handler to start the flow
One step form wireframe
This form must consist of the following mandatory fields:
- Heights (input)
- Gender (radio buttons)
- Front photo (take photo)
- Side photo (take photo)
- Continue (button)
Height input field(s)
Height must be more or equal to 150cm (4’ 11”) and less or equal to 220cm (7’ 2”).
Min height in cm. Height should be more or equal to 150cm
Max height in cm. Height should be less or equal to 220cm
Min height in inches. Height should be more or equal to 4’ 11’’
Max height in inches. Height should be less or equal to 7’ 2’’
/**
* Convert centimeters value to feet and inches
*
* @param {number} cm - centimeters
* @returns {Object} object with foot-inch values
*/
const cmToFtIn = (cm) => {
const inches = cm / 2.54;
const ft = inches / 12;
return {
ft: Math.floor(ft),
in: Math.ceil(inches.toFixed(0) % 12),
};
};
Function for converting centimeters to foot-inch values:
/**
* Convert inches to centimeters
*
* @param {number} inches - inches
* @returns {number} centimeters value
*/
const in2cm = inches => inches * 2.54;
Function for converting inches to centimeters:
/**
* Convert ft to in value
*
* @param {number} ft - foot value
* @returns {number} inch value
*/
const ft2in = ft => ft * 12;
Function for converting feet to inches:
/**
* Convert ft and in height to cm value
*
* @param {number} ft - foot value
* @param {number} inches - inch value
*/
const getHeightCm = (ft = 0, inches = 0) => {
return in2cm(ft2in(ft) + parseInt(inches, 10));
};
Function for converting foot-inch value to centimeters
Gender radio buttons
The best practice is to show the outlines of the body according to the specified gender
Gender specified as Female
Gender specified as Male
Slots for front and side photos
1. When the slots are empty
In the description of each slot, a user must see the full information about what must be done:
- which type of photo must be taken: Front photo or Side photo
- what a user needs to do: Click here to take a photo
2. User has taken photos
Image rotation fix https://gist.github.com/pisarivskiy/b68a5bd3e31c59586f99c60008e6f9eb#file-image-orientation-fix-example-js
$('#load-file').on('change', function () {
var file = $(this).files[0];
getOrientation(file)
.then(function (fixOrientation) {
return loadPhoto(file, fixOrientation);
})
.then(function (file) {
img.attr('src', file);
})
.catch(function (err) {
console.log(err);
});
});
This code checks EXIF flag in the image file metadata and rotates it based on this flag. You need to get a blob object from input element with change event.
The result of loadPhoto method (base64 encoded image) can be sent to our API.
If a user fills in the form correctly
function handleSubtaskErrors(subtasks) {
const front = subtasks.filter(function (item) { return item.name.indexOf('front_') !== -1; })[0];
const side = subtasks.filter(function (item) { return item.name.indexOf('side_') !== -1; })[0];
if (front && front.status === 'FAILURE') {
frontPhoto.classList.add('error');
}
if (side && side.status === 'FAILURE') {
sidePhoto.classList.add('error');
}
}
Errors messages and errors validation
If saia.api.queue.getResults returns an error, you could handle it in the following way to properly identify the image that produces the error
Errors messages and errors validation
Recommendations: Please retake the photo.
Check if you’ve followed through all of our recommendations:
- Your entire body should be visible in the photos from head to toe.
- Wear tight-fitted clothing to clearly depict body contour
- Remove shoes, do not wear heels or platforms
- Remove belts and wallets, anything that will obstruct the body parts
- Tie up hair into a bun so shoulders and neck are visible
- For the front photo, stand straight with feet apart to clearly show the full contour of legs from crotch to floor. Arms should extend away from the body in an “A” pose to depict full body contour. Stand straight with good posture, head facing forward at the camera.
- For side photos, turn to the left and stand with feet and legs together touching. Arms and hands should be straight down, resting on hips and thighs. Ensure that the front and back are visible and that arms and hands are not obstructing the image. Stand straight with good posture, head facing forward and not at the camera.
If a user took a wrong front photo
Recommendations:
Please retake the photo.
Check if you’ve followed through all of our recommendations:
- Your entire body should be visible in the photos from head to toe.
- Wear tight-fitted clothing to clearly depict body contour
- Remove shoes, do not wear heels or platforms
- Remove belts and wallets, anything that will obstruct the body parts
- Tie up hair into a bun so shoulders and neck are visible
- For the front photo, stand straight with feet apart to clearly show the full contour of legs from crotch to floor. Arms should extend away from the body in an “A” pose to depict full body contour. Stand straight with good posture, head facing forward at the camera.
- For side photos, turn to the left and stand with feet and legs together touching. Arms and hands should be straight down, resting on hips and thighs. Ensure that the front and back are visible and that arms and hands are not obstructing the image. Stand straight with good posture, head facing forward and not at the camera.
If a user took a wrong side photo
Recommendations:
Please retake the photo.
Check if you’ve followed through all of our recommendations:
- Your entire body should be visible in the photos from head to toe.
- Wear tight-fitted clothing to clearly depict body contour
- Remove shoes, do not wear heels or platforms
- Remove belts and wallets, anything that will obstruct the body parts
- Tie up hair into a bun so shoulders and neck are visible
- For the front photo, stand straight with feet apart to clearly show the full contour of legs from crotch to floor. Arms should extend away from the body in an “A” pose to depict full body contour. Stand straight with good posture, head facing forward at the camera.
- For side photos, turn to the left and stand with feet and legs together touching. Arms and hands should be straight down, resting on hips and thighs. Ensure that the front and back are visible and that arms and hands are not obstructing the image. Stand straight with good posture, head facing forward and not at the camera.
Two step form wireframe
The form in can be done in two steps. See the example below:
Mandatory fields for the First Step:
- Gender (radio buttons)
- Height (input field)
- Switcher cm/inches
- Next Step (button)
Mandatory fields for the Second Step:
- Front photo (take a photo)
- Side photo (take a photo)
- Get your size (button)
Postman Examples
- Create Person - postman collection