NAV Navbar
back icon Back
shell python javascript
Contact us

for a Developer API Key

Perfect Fit

Introduction

Welcome to the SAIA Perfect Fit API Documentation! You can use Size Chart API - to upload your size charts, Create Person API - to get measurements for a person, Size Recommendation API - to get size recommendations by uploaded size charts for an exact 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": "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 SAIA admin panel.

For clients to authenticate, 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

Quick Start

Requests Diagram

SAIA Perfect Fit API's sequence diagram:

UML

Postman examples

Correct Flow

To start a body params calculation, you need to create a Person object. Complete Person with all the required data for calculations, you can build it in two ways. It depends on your option to send base64 encoded photos:

Single Request

If it's ok for you to decode photos to Base64 format, you can:

Two Requests

If you'd like to send photos as files:

Correctly GET results

Incorrect Photo

If you got an error on the calculation task of side or front photo, you can:

Soft Validation Parameters

Parameter Validation Description
legs_distance > 2, < 15 Distance between legs, in cm
body_area_percentage = 0.7 Percentage of body on the photo

SizeCharts

Create a New SizeChart

import requests

headers = {
    'Authorization': 'APIKey <YOUR_API_KEY_HERE>',
    'Content-Type': 'application/json'
}

payload = {
    "gender": "female",
    "body_part": "top",
    "size_alpha": "M",
    "chest_top_border": 98,
    "chest_bottom_border": 93,
    "waist_top_border": 88,
    "waist_bottom_border": 83,
    "hips_top_border": 88,
    "hips_bottom_border": 83,
    "low_hips_top_border": 85,
    "low_hips_bottom_border": 80,
    "brand": "Puma",
    "categories": [
        "TShirt",
        "Hoodie"
    ],
    "shop": "https://your_shop.com"
}

response = requests.request('POST', 'https://saia.3dlook.me/api/v2/sizecharts/', data=payload, headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/sizecharts/"
  -X POST
  -H "Authorization: APIKey <YOUR_API_KEY_HERE>"
  -d '{
    "gender": "female",
    "body_part": "top",
    "size_alpha": "M",
    "chest_top_border": 98,
    "chest_bottom_border": 93,
    "waist_top_border": 88,
    "waist_bottom_border": 83,
    "hips_top_border": 88,
    "hips_bottom_border": 83,
    "low_hips_top_border": 85,
    "low_hips_bottom_border": 80,
    "brand": "Puma",
    "categories": [
        "TShirt",
        "Hoodie"
    ],
    "shop": "https://your_shop.com"
}'
var payload = {
    "gender": "female",
    "body_part": "top",
    "size_alpha": "M",
    "chest_top_border": 98,
    "chest_bottom_border": 93,
    "waist_top_border": 88,
    "waist_bottom_border": 83,
    "hips_top_border": 88,
    "hips_bottom_border": 83,
    "low_hips_top_border": 85,
    "low_hips_bottom_border": 80,
    "brand": "Puma",
    "categories": [
        "TShirt",
        "Hoodie"
    ],
    "shop": "https://your_shop.com"
}

var settings = {
    "async": true,
    "crossDomain": true,
    "url": "https://saia.3dlook.me/api/v2/sizecharts/",
    "method": "POST",
    "headers": {
    "Content-Type": "application/json",
        "Authorization": "APIKey <YOUR_API_KEY_HERE>",
        },
    "processData": false,
    "data": payload
}

$.ajax(settings).done(function (response) {
console.log(response);
});

The above command returns JSON structured like this:

{
    "id": 16528,
    "gender": "female",
    "body_part": "top",
    "size_alpha": "M",
    "size_num": "",
    "chest_top_border": "98.00",
    "chest_bottom_border": "93.00",
    "waist_top_border": "88.00",
    "waist_bottom_border": "83.00",
    "hips_top_border": "88.00",
    "hips_bottom_border": "83.00",
    "low_hips_top_border": "85.00",
    "low_hips_bottom_border": "80.00",
    "shop": "https://your_shop.com",
    "brand": "Puma",
    "categories": [
        "TShirt",
        "Hoodie"
    ]
}

This endpoint creates a new size chart. If shop, brand, or categories do not exist, then it is created.

HTTP Request

POST https://saia.3dlook.me/api/v2/sizecharts/

Request Body

The request body should be an "application/json" encoded object, containing the following items.

Parameter Type Validation Description
gender string male or female gender, male or female
body_part string top or bottom or dress body part of cloth
size_alpha string any string length<10 letter size name
size_num string any string length<10 numeric size name
chest_top_border float any float value of chest top border
chest_bottom_border float any float value of chest bottom border
waist_top_border float any float value of waist top border
waist_bottom_border float any float value of waist bottom border
hips_top_border float any float value of hips top border
hips_bottom_border float any float value of hips bottom border
low_hips_top_border float any float value of low_hips top border
low_hips_bottom_border float any float value of low_hips bottom border
shop string valid url with length<300 shop url
brand string any string with length<40 brand name
categories list of string list of strings length<30 list of categories

Bulk Create a New SizeCharts

import requests

headers = {
    'Authorization': 'APIKey <YOUR_API_KEY_HERE>',
    'Content-Type': 'application/json'
}

payload = [
    {
        "gender": "female",
        "body_part": "top",
        "size_alpha": "M",
        "chest_top_border": 98,
        "chest_bottom_border": 93,
        "waist_top_border": 88,
        "waist_bottom_border": 83,
        "hips_top_border": 88,
        "hips_bottom_border": 83,
        "low_hips_top_border": 85,
        "low_hips_bottom_border": 80,
        "brand": "Puma",
        "categories": [
            "TShirt",
            "Hoodie"
        ],
        "shop": "https://your_shop.com"
    },
    {
        "gender": "female",
        "body_part": "top",
        "size_alpha": "L",
        "chest_top_border": 105,
        "chest_bottom_border": 98,
        "waist_top_border": 95,
        "waist_bottom_border": 88,
        "hips_top_border": 94,
        "hips_bottom_border": 88,
        "low_hips_top_border": 92,
        "low_hips_bottom_border": 85,
        "brand": "Puma",
        "categories": [
            "TShirt",
            "Hoodie"
        ],
        "shop": "https://your_shop.com"
    },
    {
        "gender": "female",
        "body_part": "top",
        "size_alpha": "L",
        "chest_top_border": 112,
        "chest_bottom_border": 105,
        "waist_top_border": 103,
        "waist_bottom_border": 95,
        "hips_top_border": 102,
        "hips_bottom_border": 94,
        "low_hips_top_border": 99,
        "low_hips_bottom_border": 92,
        "brand": "Puma",
        "categories": [
            "TShirt",
            "Hoodie"
        ],
        "shop": "https://your_shop.com"
    }
]
response = requests.request('POST', 'https://saia.3dlook.me/api/v2/sizecharts/', data=payload, headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/sizecharts/"
  -X POST
  -H "Authorization: APIKey <YOUR_API_KEY_HERE>"
  -d '[
    {
        "gender": "female",
        "body_part": "top",
        "size_alpha": "M",
        "chest_top_border": 98,
        "chest_bottom_border": 93,
        "waist_top_border": 88,
        "waist_bottom_border": 83,
        "hips_top_border": 88,
        "hips_bottom_border": 83,
        "low_hips_top_border": 85,
        "low_hips_bottom_border": 80,
        "brand": "Puma",
        "categories": [
            "TShirt",
            "Hoodie"
        ],
        "shop": "https://your_shop.com"
    },
    {
        "gender": "female",
        "body_part": "top",
        "size_alpha": "L",
        "chest_top_border": 105,
        "chest_bottom_border": 98,
        "waist_top_border": 95,
        "waist_bottom_border": 88,
        "hips_top_border": 94,
        "hips_bottom_border": 88,
        "low_hips_top_border": 92,
        "low_hips_bottom_border": 85,
        "brand": "Puma",
        "categories": [
            "TShirt",
            "Hoodie"
        ],
        "shop": "https://your_shop.com"
    },
    {
        "gender": "female",
        "body_part": "top",
        "size_alpha": "L",
        "chest_top_border": 112,
        "chest_bottom_border": 105,
        "waist_top_border": 103,
        "waist_bottom_border": 95,
        "hips_top_border": 102,
        "hips_bottom_border": 94,
        "low_hips_top_border": 99,
        "low_hips_bottom_border": 92,
        "brand": "Puma",
        "categories": [
            "TShirt",
            "Hoodie"
        ],
        "shop": "https://your_shop.com"
    }
]'
var payload = [
    {
        "gender": "female",
        "body_part": "top",
        "size_alpha": "M",
        "chest_top_border": 98,
        "chest_bottom_border": 93,
        "waist_top_border": 88,
        "waist_bottom_border": 83,
        "hips_top_border": 88,
        "hips_bottom_border": 83,
        "low_hips_top_border": 85,
        "low_hips_bottom_border": 80,
        "brand": "Puma",
        "categories": [
            "TShirt",
            "Hoodie"
        ],
        "shop": "https://your_shop.com"
    },
    {
        "gender": "female",
        "body_part": "top",
        "size_alpha": "L",
        "chest_top_border": 105,
        "chest_bottom_border": 98,
        "waist_top_border": 95,
        "waist_bottom_border": 88,
        "hips_top_border": 94,
        "hips_bottom_border": 88,
        "low_hips_top_border": 92,
        "low_hips_bottom_border": 85,
        "brand": "Puma",
        "categories": [
            "TShirt",
            "Hoodie"
        ],
        "shop": "https://your_shop.com"
    },
    {
        "gender": "female",
        "body_part": "top",
        "size_alpha": "L",
        "chest_top_border": 112,
        "chest_bottom_border": 105,
        "waist_top_border": 103,
        "waist_bottom_border": 95,
        "hips_top_border": 102,
        "hips_bottom_border": 94,
        "low_hips_top_border": 99,
        "low_hips_bottom_border": 92,
        "brand": "Puma",
        "categories": [
            "TShirt",
            "Hoodie"
        ],
        "shop": "https://your_shop.com"
    }
]

var settings = {
    "async": true,
    "crossDomain": true,
    "url": "https://saia.3dlook.me/api/v2/sizecharts/",
    "method": "POST",
    "headers": {
    "Content-Type": "application/json",
        "Authorization": "APIKey <YOUR_API_KEY_HERE>",
        },
    "processData": false,
    "data": payload
}

$.ajax(settings).done(function (response) {
console.log(response);
});

The above command returns JSON structured like this:

[
  {
    "id": 16529,
    "gender": "female",
    "body_part": "top",
    "size_alpha": "M",
    "size_num": "",
    "chest_top_border": "98.00",
    "chest_bottom_border": "93.00",
    "waist_top_border": "88.00",
    "waist_bottom_border": "83.00",
    "hips_top_border": "88.00",
    "hips_bottom_border": "83.00",
    "low_hips_top_border": "85.00",
    "low_hips_bottom_border": "80.00",
    "shop": "https://your_shop.com",
    "brand": "Puma",
    "categories": [
      "TShirt",
      "Hoodie"
    ]
  },
  {
    "id": 16530,
    "gender": "female",
    "body_part": "top",
    "size_alpha": "L",
    "size_num": "",
    "chest_top_border": "105.00",
    "chest_bottom_border": "98.00",
    "waist_top_border": "95.00",
    "waist_bottom_border": "88.00",
    "hips_top_border": "94.00",
    "hips_bottom_border": "88.00",
    "low_hips_top_border": "92.00",
    "low_hips_bottom_border": "85.00",
    "shop": "https://your_shop.com",
    "brand": "Puma",
    "categories": [
      "TShirt",
      "Hoodie"
    ]
  },
  {
    "id": 16531,
    "gender": "female",
    "body_part": "top",
    "size_alpha": "L",
    "size_num": "",
    "chest_top_border": "112.00",
    "chest_bottom_border": "105.00",
    "waist_top_border": "103.00",
    "waist_bottom_border": "95.00",
    "hips_top_border": "102.00",
    "hips_bottom_border": "94.00",
    "low_hips_top_border": "99.00",
    "low_hips_bottom_border": "92.00",
    "shop": "https://your_shop.com",
    "brand": "Puma",
    "categories": [
      "TShirt",
      "Hoodie"
    ]
  }
]

This endpoint creates a few new size charts. If shop, brand, or categories do not exist, then it is created.

HTTP Request

POST https://saia.3dlook.me/api/v2/sizecharts/

Request Body

The request body should be an "application/json" encoded object, containing the following items.

Parameter Type Validation Description
gender string male or female gender, male or female
body_part string top or bottom or dress body part of cloth
size_alpha string any string length<10 letter size name
size_num string any string length<10 numeric size name
chest_top_border float any float value of chest top border
chest_bottom_border float any float value of chest bottom border
waist_top_border float any float value of waist top border
waist_bottom_border float any float value of waist bottom border
hips_top_border float any float value of hips top border
hips_bottom_border float any float value of hips bottom border
low_hips_top_border float any float value of low_hips top border
low_hips_bottom_border float any float value of low_hips bottom border
shop string valid url with length<300 shop url
brand string any string with length<40 brand name
categories list of string list of strings length<30 list of categories

Get a Specific Size chart

import requests

headers = {
    'Authorization': 'APIKey <YOUR_API_KEY_HERE>'
}

response = requests.request('GET', 'https://saia.3dlook.me/api/v2/sizecharts/16398/', headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/sizecharts/16398/"
  -H "Authorization: APIKey <YOUR_API_KEY_HERE>"
var settings = {
    "async": true,
    "crossDomain": true,
    "url": "https://saia.3dlook.me/api/v2/sizecharts/16398/",
    "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": 16398,
    "gender": "female",
    "body_part": "top",
    "size_alpha": "",
    "size_num": "32",
    "chest_top_border": "98.81",
    "chest_bottom_border": "93.98",
    "waist_top_border": "88.65",
    "waist_bottom_border": "83.82",
    "hips_top_border": null,
    "hips_bottom_border": null,
    "low_hips_top_border": null,
    "low_hips_bottom_border": null,
    "shop": "https://your_shop.com",
    "brand": "Puma",
    "categories": [
        "TShirt",
        "Hoodie"
    ]
}

This endpoint retrieves a specific size chart.

HTTP Request

GET https://saia.3dlook.me/api/v2/sizecharts/<id>/

URL Parameters

The following parameters should be included in the URL path.

Parameter Description
id The ID of the specific sizechart.

Update a Specific SizeChart

import requests

headers = {
    'Authorization': 'APIKey <YOUR_API_KEY_HERE>',
    'Content-Type': 'application/json'
}

payload = {
    "gender": "female",
    "body_part": "top",
    "size_alpha": "M",
    "chest_top_border": 98,
    "chest_bottom_border": 93,
    "waist_top_border": 88,
    "waist_bottom_border": 83,
    "hips_top_border": 88,
    "hips_bottom_border": 83,
    "low_hips_top_border": 85,
    "low_hips_bottom_border": 80,
    "brand": "Puma",
    "categories": [
        "TShirt",
        "Hoodie"
    ],
    "shop": "https://your_shop.com"
}

response = requests.request('PUT', 'https://saia.3dlook.me/api/v2/sizecharts/16398/', data=payload, headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/sizecharts/16398/"
  -X PUT
  -H "Authorization: APIKey <YOUR_API_KEY_HERE>"
  -d '{
    "gender": "female",
    "body_part": "top",
    "size_alpha": "M",
    "chest_top_border": 98,
    "chest_bottom_border": 93,
    "waist_top_border": 88,
    "waist_bottom_border": 83,
    "hips_top_border": 88,
    "hips_bottom_border": 83,
    "low_hips_top_border": 85,
    "low_hips_bottom_border": 80,
    "brand": "Puma",
    "categories": [
        "TShirt",
        "Hoodie"
    ],
    "shop": "https://your_shop.com"
}'
var payload = {
    "gender": "female",
    "body_part": "top",
    "size_alpha": "M",
    "chest_top_border": 98,
    "chest_bottom_border": 93,
    "waist_top_border": 88,
    "waist_bottom_border": 83,
    "hips_top_border": 88,
    "hips_bottom_border": 83,
    "low_hips_top_border": 85,
    "low_hips_bottom_border": 80,
    "brand": "Puma",
    "categories": [
        "TShirt",
        "Hoodie"
    ],
    "shop": "https://your_shop.com"
}

var settings = {
    "async": true,
    "crossDomain": true,
    "url": "https://saia.3dlook.me/api/v2/sizecharts/16398/",
    "method": "PUT",
    "headers": {
    "Content-Type": "application/json",
        "Authorization": "APIKey <YOUR_API_KEY_HERE>",
        },
    "processData": false,
    "data": payload
}

$.ajax(settings).done(function (response) {
console.log(response);
});

The above command returns JSON structured like this:

{
    "id": 16398,
    "gender": "female",
    "body_part": "top",
    "size_alpha": "M",
    "size_num": "",
    "chest_top_border": "98.00",
    "chest_bottom_border": "93.00",
    "waist_top_border": "88.00",
    "waist_bottom_border": "83.00",
    "hips_top_border": "88.00",
    "hips_bottom_border": "83.00",
    "low_hips_top_border": "85.00",
    "low_hips_bottom_border": "80.00",
    "shop": "https://your_shop.com",
    "brand": "Puma",
    "categories": [
        "TShirt",
        "Hoodie"
    ]
}

This endpoint updates a specific size chart. If shop, brand, or categories do not exist, then it is created.

HTTP Request

PUT https://saia.3dlook.me/api/v2/sizecharts/<id>/

URL Parameters

The following parameters should be included in the URL path.

Parameter Description
id The ID of the specific sizechart.

Request Body

The request body should be an "application/json" encoded object, containing the following items.

Parameter Type Validation Description
gender string male or female gender, male or female
body_part string top or bottom or dress body part of cloth
size_alpha string any string length<10 letter size name
size_num string any string length<10 numeric size name
chest_top_border float any float value of chest top border
chest_bottom_border float any float value of chest bottom border
waist_top_border float any float value of waist top border
waist_bottom_border float any float value of waist bottom border
hips_top_border float any float value of hips top border
hips_bottom_border float any float value of hips bottom border
low_hips_top_border float any float value of low_hips top border
low_hips_bottom_border float any float value of low_hips bottom border
shop string valid url with length<300 shop url
brand string any string with length<40 brand name
categories list of string list of strings length<30 list of categories

Delete a Specific Size chart

import requests

headers = {
    'Authorization': 'APIKey <YOUR_API_KEY_HERE>'
}

response = requests.request('DELETE', 'https://saia.3dlook.me/api/v2/sizecharts/16398/', headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/sizecharts/16398/"
  -X DELETE
  -H "Authorization: APIKey <YOUR_API_KEY_HERE>"
var settings = {
    "async": true,
    "crossDomain": true,
    "url": "https://saia.3dlook.me/api/v2/sizecharts/16398/",
    "method": "DELETE",
    "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:

http_code 204

This endpoint deletes a specific size chart.

HTTP Request

DELETE https://saia.3dlook.me/api/v2/sizecharts/<id>/

URL Parameters

The following parameters should be included in the URL path.

Parameter Description
id The ID of the specific size chart.

List All SizeCharts

import requests

headers = {
    'Authorization': 'APIKey <YOUR_API_KEY_HERE>'
}

response = requests.request('GET', 'https://saia.3dlook.me/api/v2/sizecharts/', headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/sizecharts/"
  -H "Authorization: APIKey <YOUR_API_KEY_HERE>"
var settings = {
    "async": true,
    "crossDomain": true,
    "url": "https://saia.3dlook.me/api/v2/sizecharts/",
    "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/sizecharts/?page=2",
  "previous": null,
  "results": [
    {
      "id": 16517,
      "gender": "female",
      "body_part": "top",
      "size_alpha": "M",
      "size_num": "",
      "chest_top_border": "98.81",
      "chest_bottom_border": "93.98",
      "waist_top_border": "88.65",
      "waist_bottom_border": "83.82",
      "hips_top_border": null,
      "hips_bottom_border": null,
      "low_hips_top_border": null,
      "low_hips_bottom_border": null,
      "shop": "https://your_shop.com",
      "brand": "Puma",
      "categories": [
        "TShirt",
        "Hoodie"
      ]
    },
    {
      "id": 16398,
      "gender": "female",
      "body_part": "top",
      "size_alpha": "",
      "size_num": "32",
      "chest_top_border": "98.81",
      "chest_bottom_border": "93.98",
      "waist_top_border": "88.65",
      "waist_bottom_border": "83.82",
      "hips_top_border": null,
      "hips_bottom_border": null,
      "low_hips_top_border": null,
      "low_hips_bottom_border": null,
      "shop": "https://your_shop.com",
      "brand": "Puma",
      "categories": [
        "TShirt",
        "Hoodie"
      ]
    }
  ]
}

This endpoint retrieves all your existing size charts.

HTTP Request

GET https://saia.3dlook.me/api/v2/sizecharts/

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.

Person

Correct Flow

To start body params calculation, 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 possibilities to send base64 encoded photos:

Single Request

If it's possible for you to decode pictures to a Base64 format, you can:

Two Requests

If you'd like to send photos as files:

Correctly GET results

Incorrect Photo

If you got an error on the calculation task of side or front photo, you can:

Soft Validation Parameters

Parameter Validation Description
legs_distance > 2, < 15 Distance between legs, in cm
body_area_percentage = 0.7 Percentage of body on the photo

Create a New Person

import requests

headers = {
    'Authorization': 'APIKey <YOUR_API_KEY_HERE>',
    'Content-Type': 'application/json'
}

payload = {
    'gender': 'female',
    'height': 170
}

response = requests.request('POST', 'https://saia.3dlook.me/api/v2/persons/', data=payload, headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/persons/"
  -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/",
    "method": "POST",
    "headers": {
    "Content-Type": "application/json",
        "Authorization": "APIKey <YOUR_API_KEY_HERE>",
        },
    "processData": false,
    "data": 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/",
    "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/

Request Body

The request body should be an "application/json" encoded object, containing the following items.

Parameter Type Validation Description
gender string male or female gender of person, male or female
height integer > 150, < 220 height of person, in cm
weight float float 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

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/', files=files, headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/persons/3/"
  -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", "path_to_file");
form.append("side_image", "path_to_file");

var settings = {
    "async": true,
    "crossDomain": true,
    "url": "https://saia.3dlook.me/api/v2/persons/3/",
    "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>/

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

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", "path_to_file");
form.append("side_image", "path_to_file");

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 photos side or front in case you'd like to rerun a 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/2/', headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/persons/2/"
  -H "Authorization: APIKey <YOUR_API_KEY_HERE>"
var settings = {
    "async": true,
    "crossDomain": true,
    "url": "https://saia.3dlook.me/api/v2/persons/2/",
    "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": 2,
    "url": "https://saia.3dlook.me/api/v2/persons/2/",
    "gender": "male",
    "height": 200,
    "front_params": {"..."},
    "side_params": {"..."},
    "volume_params": {"..."}
}

This endpoint retrieves a specific person with calculated params after all calculation tasks are 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": 1483,
    "next": "https://saia.3dlook.me/api/v2/persons/?page=2",
    "previous": null,
    "results": [
        {
            "id": 22,
            "url": "https://saia.3dlook.me/api/v2/persons/22/",
            "gender": "male",
            "height": 200,
            "front_params": {"..."},
            "side_params": {"..."},
            "volume_params": {"..."}
        },
        {
            "id": 1,
            "url": "https://saia.3dlook.me/api/v2/persons/1/",
            "gender": "male",
            "height": 200,
            "front_params": {"..."},
            "side_params": {"..."},
            "volume_params": {"..."}
        }
    ]
}

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/2/calculate/', headers=headers)
print(response.text)
curl "https://saia.3dlook.me/api/v2/persons/2/calculate/"
  -H "Authorization: APIKey <YOUR_API_KEY_HERE>"
var settings = {
    "async": true,
    "crossDomain": true,
    "url": "https://saia.3dlook.me/api/v2/persons/2/calculate/",
    "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 manually runs calculations of all params after Partial Update of photos of a specific person. As a result, you will get a URL for task_set where you can track the info.

HTTP Request

GET https://saia.3dlook.me/api/v2/persons/<id>/calculate/

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:

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

Size Recommendation

Get a Size Recommendation

import requests

headers = {
    'Authorization': "APIKey <YOUR_API_KEY_HERE>"
}

params = {"brand":"Nike","gender":"male","body_part":"bottom","waist":"76","chest":"88","hips":"90"}

response = requests.request('GET', 'https://saia.3dlook.me/api/v2/sizecharts/size/recommendation/', headers=headers, params=params)
print(response.text)
curl "https://saia.3dlook.me/api/v2/sizecharts/size/recommendation/?brand=Nike&gender=male&body_part=bottom&waist=76&chest=88&hips=90'"
  -H "Authorization: APIKey <YOUR_API_KEY_HERE>"
var settings = {
    "async": true,
    "crossDomain": true,
    "url": "https://saia.3dlook.me/api/v2/sizecharts/size/recommendation/?brand=Nike&gender=male&body_part=bottom&waist=76&chest=88&hips=90",
    "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:

{
    "normal": {
        "size": "XS",
        "accuracy": 0.4875000000000007,
        "parameter": "hips"
    },
    "loose": {
        "size": "S",
        "accuracy": 0.45505617977528046,
        "parameter": "waist"
    }
}

This endpoint retrieves all your existing persons with calculations.

HTTP Request

GET https://saia.3dlook.me/api/v2/sizecharts/size/recommendation/

Query Parameters

The following parameters should be included as part of the URL query string.

Parameter Default Description
brand Target brand name
body_part top or dress or bottom
gender male or female
chest chest volume measurement of body
waist waist volume measurement of body
hips hips volume measurement of body

Integration

Widget for SAIA Perfect Fit API

Widget, that implements getting garment size for the user based on SAIA Perfect Fit API.

Add Widget via GTM

First, you should include a button script to your site page. To do this, go to Google Tag Manager and log in to your account. Once you’re in, select New Tag.

New Tag

On the next page, set a label for a new script and select Tag Configuration.

Tag Configuration

Next, select Custom HTML

Tag Configuration

<script src="https://pf-widget.3dlook.me/saia-pf-button.js"></script>
<script src="https://pf-widget.3dlook.me/saia-pf-button.js"></script>
<script src="https://pf-widget.3dlook.me/saia-pf-button.js"></script>

With the next popup, paste in the following code and set firing triggers to All pages

Tag Configuration

After that, hit the Publish button that has appeared in the top right corner to send changes to your website.

Tag Configuration

<script>
  (async () => {
    const button = new SaiaButton({
      // widget container element selector
      container: '.product-single__meta',
      // your SAIA API key
      key: 'fnqiwhf9v9y9ty13bt783yugyiurygb3v78gvt',
      // widget domain
      widgetUrl: 'https://pf-widget.3dlook.me/',
      // brand name
      brand: 'Nike',
      // body part
      bodyPart: 'top',
      // product information
      product: {
        // product image url for results page
        imageUrl: 'https://imagehost.com/images/products/product.jpg',
        // product description for results page
        description: 'The Nike Air Rally Women\'s Crew',
      },
    });

    // init button
    button.init();

    // try to get size recommendation for user,
    // that already has passed the widget flow
    // and has its measurements in localStorage
    const recommendations = await button.getSize();

    // display size recommendations
    if (recommendations) {
      button.displaySize(recommendations);
    }
  })();
</script>
<script>
  (async () => {
    const button = new SaiaButton({
      // widget container element selector
      container: '.product-single__meta',
      // your SAIA API key
      key: 'fnqiwhf9v9y9ty13bt783yugyiurygb3v78gvt',
      // widget domain
      widgetUrl: 'https://pf-widget.3dlook.me/',
      // brand name
      brand: 'Nike',
      // body part
      bodyPart: 'top',
      // product information
      product: {
        // product image url for results page
        imageUrl: 'https://imagehost.com/images/products/product.jpg',
        // product description for results page
        description: 'The Nike Air Rally Women\'s Crew',
      },
    });

    // init button
    button.init();

    // try to get size recommendation for user,
    // that already has passed the widget flow
    // and has its measurements in localStorage
    const recommendations = await button.getSize();

    // display size recommendations
    if (recommendations) {
      button.displaySize(recommendations);
    }
  })();
</script>
<script>
  (async () => {
    const button = new SaiaButton({
      // widget container element selector
      container: '.product-single__meta',
      // your SAIA API key
      key: 'fnqiwhf9v9y9ty13bt783yugyiurygb3v78gvt',
      // widget domain
      widgetUrl: 'https://pf-widget.3dlook.me/',
      // brand name
      brand: 'Nike',
      // body part
      bodyPart: 'top',
      // product information
      product: {
        // product image url for results page
        imageUrl: 'https://imagehost.com/images/products/product.jpg',
        // product description for results page
        description: "The Nike Air Rally Women\'s Crew",
      },
    });

    // init button
    button.init();

    // try to get size recommendation for user,
    // that already has passed the widget flow
    // and has its measurements in localStorage
    const recommendations = await button.getSize();

    // display size recommendations
    if (recommendations) {
      button.displaySize(recommendations);
    }
  })();
</script>

When you include the button script to your website page, you should initialize it with proper parameters. The initialization code will look something like this:

Javascript SDK for SAIA Perfect Fit API

SAIA Javascript SDK can work in two modes: as a widget and as an API wrapper.

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 uploaded photos could not be processed.
429 Too Many Requests -- You are sending too many requests.
500 Internal Server Error -- A server error occured. Try again later.
503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.

Size Recommendation Errors

Message Meaning
sizecharts according to queried brand and gender, should be more than 2 Sizecharts, which you created earlier should be more than one.
no sizecharts found according to your query No sizecharts match to your query params.

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 uploaded 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.
902 The detected object is not human The detected object in the photo is not a human body and it cannot be processed.
903 Side photo in the front The photo uploaded to the Front slot 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).

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:

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';

      return saia.api.sizechart.getSize({
        gender: 'female',
        hips: person.volume_params.hips,
        chest: person.volume_params.chest,
        waist: person.volume_params.waist,
        body_part: 'top',
        brand: 'Nike',
      });
    })
    .then((sizeRecomendations) => {
      status.innerHTML = 'Finished';

      // print the result out
      results.innerHTML = JSON.stringify(sizeRecomendations, 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:

One step form wireframe

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

One step form wireframe

Max height in cm. Height should be less or equal to 220cm

One step form wireframe

Min height in inches. Height should be more or equal to 4’ 11’’

One step form wireframe

Max height in inches. Height should be less or equal to 7’ 2’’

One step form wireframe

/**
 * 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 Female

Gender specified as Male

Gender specified as Male

Slots for front and side photos

1. When the slots are empty

When the slots are empty

In the description of each slot, a user must see the full information about what must be done:

2. User has uploaded photos

When the slots are empty

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

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

Errors messages and errors validation

Recommendations:

Please retake the photo.

Check if you’ve followed through all of our recommendations:

If a user uploaded a wrong front photo

If a user uploaded a wrong side photo

Recommendations:

Please retake the photo.

Check if you’ve followed through all of our recommendations:

If a user uploaded a wrong side photo

If a user uploaded a wrong side photo

Recommendations:

Please retake the photo.

Check if you’ve followed through all of our recommendations:

Two step form wireframe

The form in can be done in two steps. See the example below:

Mandatory fields for the First Step:

First Step

Mandatory fields for the Second Step:

First Step