API Developer Documentation

💡This page is intended as an in-depth overview of the essential endpoints available on the expoze.io API. If you haven't already, we recomment first take a looking at getting started with the expoze.io API to get an idea of the typical user flow.

First up, you can log in to the developer console at expoze.app and get your Postman collection to get up and running fast! The developer console can also be used to manage your account, billing details and invoices.

Authorizing user

Get the auth token

POST /auth/token

Key Type Description
username string The email of the user
password string The user password.

200 - Response success:

{

"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE2MzQ1NTk5NDAsImV4cCI6MTYzNDYyMDQyMCwicm9sZXMiOlsiUk9MRV9VU0VSIiwiUk9MRV9BRE1JTiJdLCJ1c2VybmFtZSI6ImpvaG5AYWxwaGEub25lIiwidXNlcklkIjoxLCJvcmdhbml6YXRpb24iOjEsInN1YnNjcmlwdGlvbiI6eyJwcm8iOnRydWUsImNvcmVwbHVzIjpmYWxzZSwiY29yZSI6ZmFsc2V9fQ.0wGb8ih8l6Ph1DWjMpPLtk1W5Q6a2w0KxawrTzVTdhX9OZw7e7CpILFoph75ikGX6j1ZwIZHEmMUOein5n2cLcKEUXwWH-b3l97Qrgm-K00Bupyv2J-uZLjM--3XCKMgI8qvgxzU_R9iYNsYIjz06eEs6QdRUgWnt49KSQ1_qoyvbvITI3UY51uY_TzxaUxcWbF7KJylW_ilLTCuehFrNIT_V0K6pHQv-b_mlbau0mXCoef0sgDmUye1Z0cLLUvsMf3XpQiXy9b7DEzKK1jqkg928miO__6zEQkgcAPeH-pCZwpgaT3XqMQD-20aQWPkFSBp4e7uuVTQKHYNQCA8Uw",

"refresh_token": "32506d6669a4b229b04292e1186a7252648a67bb35982de9c3d44613629028103a1acda9a92cbb4414acbf8aaf0391d9c2dd4ba5418e91388e38ef28fd06cf58"

}


401 - Unauthorized

{

"code": 401,

"message": "Invalid credentials."

}



Get the refresh token

POST /auth/token/refresh

Key Type Description
username string The email of the user
password string The user password.

200 - Unauthorised

{

"code": 401,

"message": "An authentication exception occurred."

}


401 - Response success:

{

"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE2ODI0MTc0NDIsImV4cCI6MTY4MjQ3NzkyMiwicm9sZXMiOlsiUk9MRV9VU0VSIiwiUk9MRV9BRE1JTiIsIlJPTEVfQVBJX1VTRVIiXSwidXNlcm5hbWUiOiJkYWFuK2FwaUBleHBvemUuaW8iLCJ1c2VySWQiOjQ1OTA5LCJvcmdhbml6YXRpb24iOjQ0NjI3LCJzdWJzY3JpcHRpb24iOnsicHJvIjpmYWxzZSwiY29yZXBsdXMiOmZhbHNlLCJjb3JlIjpmYWxzZX19.tVodc5sBgvIJrZ_ogtHG6WNxYqHDQHJobFCoa1qWa4fEQukhIkgZ3cDhI_HBYfTyfwGEMUck2AoucZaUgE5VLLGJufoQpvcqvq8GPhL3D6kVz7FliXYvl4XeTvZIfvrtELpPdFD8A5RLdntAn_Hq4iRAg-N7Cixk56D7N-_ap_Wly_IVfFX06Mv5QYMNHbtHg5eEMrbm15oMBZXNJTJOwU_1xL5jTLVDLJeU_lt_2-igg6T-hk650Wxhn6604x-jMtdoYkNJI9EhfoJHJK3Rjep_outWIEYMrKxVyHds27U_0riYkExFfMXuIMa8EqlHE-kn1xB13XrPBNOrCHyJa1YuxjEWCNY6_rEKbd1vkJuC1sSsBmUMA_DfJ4OM_W1cdtVdCpLsQNZYMVpHr9sK3eLS9gbSKn_301GAGlk2wKs1WsVCMkN9MvLzf9jfmRRRXEkv1gGXoHvh2L0RbA2a6nuEDCRx0kHJSsQeBlyPjUWb6gIrlefbLqCsJ-MZKnA-ymCbIc3YdgJWdWEi9To8F7iyBGN2eZ6E4qNQscY9DiBiRcrLfehSYx83HFAn8vUzFrX2lvWYuG-_qGynkK4OYADAgFe2-HKOaQntDFlh3DWJxlOXgGA3EEK_ETnevBRp_ePTwn2TDpn0xbLP2pAzC-58UAfFZceJ0prfy3O5zu8",

"refresh_token": "c36d31774b1eddfa210a60bac31d5e0cebcdaab02cde4ff855e83661e6868c5e5de6f761ecd17f454ccbb1771144738dc72d73f2c1cd50c6de0df492030269b5"

}



Get the current user

POST /auth/me

200 - Response success:

{

"firstName": "John",

"lastName": "Doe",

"company": "Company Name",

"username": "johndoe@company.com",

"roles": [

"ROLE_USER",

"ROLE_ADMIN"

],

"organization": {

"uuid": "037faedf-eade-4f25-8def-e3f30346758e",

"stripePlanId": "plan_GTmggbYeNnxrSw",

"id": 1

},

"organizationId": 1,

"status": "active",

"avatar": null,

"lastLogin": "2021-10-18T12:31:24+00:00",

"department": null,

"jobTitle": null,

"id": 1

}


Workspaces

💡 Previously, it was required to create a workspace before you could create any jobs. However, this is no longer required.

Create a new workspace

POST /spaces

Body:

{

"organization" : <organization_id>,

"name": "Figma plugin"

"description" : "<optional>"

}


Response:

{

"organization": {

"id": 1

},

"name": "Test 2",

"description": null,

"cover": null,

"coverGrid": [],

"mediaobject": [],

"parent": null,

"parentId": null,

"children": [],

"id": 7

}


List spaces

GET /spaces.json

Images have a specific prefix to reference a specific version see (using image paths).

Response:

[

{

"organization": {

"id": 1

},

"name": "Figma",

"description": "Images processed from your Figma.",

"cover": "1\\/1\\/25\\/jobs\\/eab3a441-fb15-4df7-a4b1-e7a47dd4dce1.jpg",

"coverGrid": [

"1\\/1\\/14bd2ff8-1cfc-4e6f-a24e-bd6a3fd03a2a.jpeg",

"1\\/1\\/23\\/jobs\\/ba374b17-f5b9-4da4-bac6-b455446b65fd.jpg",

"1\\/1\\/29\\/jobs\\/bbd2d436-b841-419b-8c90-c5c0ce38e91d.jpg",

"1\\/1\\/4d179860-758d-4e8e-bb72-356c601fcd88.jpeg"

],

"mediaobject": [

{

"id": 27

},

{

"id": 23

}

],

"parent": null,

"parentId": null,

"children": [],

"id": 1

},

...

]


Uploading a new image

For uploading an image a multipart form needs to be posted to an endpoint from that specific space.

Using multipart form blob

If using workspace - POST /spaces/{spaceId}/upload

If not using workspace - POST /developer/upload

Custom headers:

Name Value
Content-Type multipart/form-data

Form parameters:

Name Value
file <blob>https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects

200 - Response success:

{

"message": "Upload accepted.",

"mediaId": 34018

}


Upload image using base_64

POST /developer/upload

Custom headers:

Name Value
Content-Type text/plain

Form parameters:

Name Value
file Base64ImageCode

200 - Response success:

{

"message": "Upload accepted.",

"mediaId": 34018

}


Add a new job

To create a new heatmap prediction, you need to create a new job. The data you provide in the body of the request will define what kind of heatmap output you will receive, for additional details take a look at the heatmap presets article or custom heatmaps article

POST /jobs.json

Images have a specific prefix to reference a specific version see (using image paths).

for the settings of the job please see Heatmap presets for the examples.

body:

{

"media": "<media_id>",

"colormap": "jet",

"alpha": 0.85,

"enableWatermark": false,

"boost": 2,

"inverse": false,

"reveal": false,

"preset": "normal"

}


200 - response:

{

"position": 1,

"status": "queued",

"media": {

"id": 1337

},

"colormap": "jet",

"spyneId": null,

"mediaId": 2364,

"priority": 1,

"alpha": 1,

"modulus": 3,

"interval": 1,

"progress": 0,

"boost": 2,

"description": null,

"outputFile": null,

"outputPath": null,

"outputPdfFile": null,

"reveal": false,

"inverse": false,

"watermark": [],

"expectedOutputUri": null,

"poster": null,

"spyneTask": null,

"preset": "normal",

"enableWatermark": null,

"progressStatus": {

"progress": null,

"frames_done": null,

"total_frames": null,

"time_elapsed": null,

"time_remaining": null

},

"salience": {

"mode": null,

"sum": null,

"min": null,

"max": null,

"mean": null,

"median": null,

"stddev": null,

"variance": null

},

"properties": {

"area": null,

"derotation": null,

"dim_height": null,

"dim_width": null,

"suffix_out": null

},

"id": 10025

}


422 - response:

{

"type": "https:\\/\\/tools.ietf.org\\/html\\/rfc2616#section-10",

"title": "An error occurred",

"detail": "tokens: There are not enough tokens left in your account to add this job.",

"violations": [

{

"propertyPath": "tokens",

"message": "There are not enough tokens left in your account to add this job.",

"code": null

}

]

}



Using image paths

The images can be prefixed with the following url prefix:

<https://api.expoze.app/core/media/cache/resolve/><preset>/userfiles/


The <preset> placeholder refers to specific sizes of the available image.

Preset Size Example
thumb_small 300 x 200 Link
thumb_medium 900 x 600 Link
thumb_large 1800 x 1200 Link
media_max 2048 x 1536 Link
original source Link

Using Webhooks

If you do not want to create a job to download the final output, you can use webhook - the system will automatically send the result to the webhook when it is ready.

First, you will need to ensure to have a unique URL from https://webhook.site/

Then, get your org ID from /organizations.json, then go to "Set up webhook" endpoint and update the request URL with the organization ID you got from /organizations.json. Send your request and after that, every time you upload your job and job is ready - the system will send json with a response to your webhook.


Creating and editing AOIs

Important to note: You cannot create an AOI without first creating a heatmap! See creating a job section for more info on how to create a heatmap.


AOIs are an important part of getting value out of expoze.io. They allow users to quantify a proportion of attention that is given to any specific area in an image, for example a brand or product. See the below screenshot for an example of how this is visualised in the expoze.io web app:

To create rectangle, circle, and triangle AOIs - POST /a_o_is.json

body:

{

"type": "rectangle",

"media": 108,

"mediaId": 108,

"media_id": 108

}

200 - response

{

"id": 108,

"position": 3,

"type": "triangle",

"media": "/images/50",

"mediaId": 50,

"points": [],

"name": null,

"score": null,

"visible": true,

"colors": []

}

An area of interest always needs coordinated within the image to quantify the amount of attention on the given area. You can edit your created AOI to adjust the point and name using the varies edit endpoints:

PUT /a_o_is.json/{aoi-id}

{

"$id": "21473",

"id": 21473,

"type": "rectangle",

"loading": false,

"editing": false,

"name": "test",

"editName": false,

"visible": true,

"selected": true,

"media": "/images/34266",

"mediaId": 34266,

"position": 0,

"points": [

{

"type": "rect",

"version": "3.6.3",

"originX": "left",

"originY": "top",

"left": 12.55,

"top": 55.55,

"width": 120,

"height": 100,

"fill": "rgba(18, 109, 88, 0.40)",

"stroke": "#005094",

"strokeWidth": 1,

"strokeDashArray": null,

"strokeLineCap": "butt",

"strokeDashOffset": 0,

"strokeLineJoin": "miter",

"strokeMiterLimit": 4,

"scaleX": 4.03,

"scaleY": 4.03,

"angle": 0,

"flipX": false,

"flipY": false,

"opacity": 1,

"shadow": null,

"visible": true,

"clipTo": null,

"backgroundColor": "",

"fillRule": "nonzero",

"paintFirst": "fill",

"globalCompositeOperation": "source-over",

"transformMatrix": null,

"skewX": 0,

"skewY": 0,

"rx": 0,

"ry": 0

}

]

}

200 - Response success

{

"id": 21473,

"position": 0,

"type": "rectangle",

"media": "/images/34266",

"mediaId": 34266,

"points": [

{

"type": "rect",

"version": "3.6.3",

"originX": "left",

"originY": "top",

"left": 12.55,

"top": 55.55,

"width": 120,

"height": 100,

"fill": "rgba(18, 109, 88, 0.40)",

"stroke": "#005094",

"strokeWidth": 1,

"strokeDashArray": null,

"strokeLineCap": "butt",

"strokeDashOffset": 0,

"strokeLineJoin": "miter",

"strokeMiterLimit": 4,

"scaleX": 4.03,

"scaleY": 4.03,

"angle": 0,

"flipX": false,

"flipY": false,

"opacity": 1,

"shadow": null,

"visible": true,

"clipTo": null,

"backgroundColor": "",

"fillRule": "nonzero",

"paintFirst": "fill",

"globalCompositeOperation": "source-over",

"transformMatrix": null,

"skewX": 0,

"skewY": 0,

"rx": 0,

"ry": 0

}

],

"name": "test",

"score": 5.1,

"visible": true,

"colors": []

}

Still need help? Get in touch Get in touch