Introduction

Welcome to the Spot API documentation. The API is currently in beta phase and we are interested in your feedback. Please read this document to get started. You can contact us at dev@spotvirtual.com if you have any questions.

Changelog

  • 01/01/2022: Spot moved from spot.xyz to spotvirtual.com.
  • 11/22/2021: Initial version.

Basics

We currently offer a REST-based API.

Authentication

Before being able to access the API, you first have to create an access token. In your Spot user's preferences, navigate to the Advanced tab and enable the Developer mode toggle. Once the developer mode has been enabled, you will notice that a new API tab have appeared in the left side menu. It is in the API tab that you can create and manage access tokens.

Authorization

You can control what your access token has access to. After creating a new token, you must decide what scopes (types of resources and level of access) and what teams the token is able to access.

Currently the API has one type of resource; worlds and entities.

You can select the level of access:

  • read-only
  • read-write access (can modify existing entities)
  • admin access (can create and delete entities)

More types will be added as we evolve the API.

Rate Limiting

At the moment we do not enforce any rate limits. We do ask that you apply common sense and do not overwhelm our API. We reserve the right to disable access tokens that cause problems.

Errors

The API aims to return proper status codes in all cases, and we recommend that you use them to see whether or not your requests were successful. If you receive errors then we recommend that you throttle and wait a moment before you retry the request. Here’s a list of common status codes and what they mean:

200 - OK
204 - No Content
400 - Bad Request
401 - Unauthorized
404 - Not Found
500 - Internal Server Error
502 - Bad Gateway
503 - Service Unavailable
504 - Gateway Timeout

Most successful requests result in the 200 status code. Some endpoints use the 204 status code to indicate a successful request (e.g. when deleting entities).

A response with the 400 status code means that the URL parameters or request data is somehow invalid.

A response with the 401 status code can means a couple of different things:

  • the access token has been deleted or disabled
  • the resource does not exist
  • you have not granted access to the resource (should probably change to 404)
  • you no longer have the required membership to the team (some actions require admin membership)

A response with the 404 status code means that the resource or entity does not exist.

5xx errors usually means that Spot is experiencing server issues, a planned downtime, or the input data was unexpected and resulted in a server error.

Making requests

Now that you have created an access token and authorized access for it, you are ready to make your first request.

Entity API Endpoint

First we need to decide what data we want to retrieve and what endpoint to use. The easiest endpoint to use is an endpoint to retrieve an entity and its properties. To get the endpoint for an object inside of Spot, simply right-click on it and click Edit.

You will notice that since Developer Mode is enabled, there’s a new text field at the bottom.

This is the endpoint for the entity itself. Click the Copy button to copy it.

Retrieve Entity Data

Use curl to retrieve the entity data:

curl -H "Authorization: Bearer spot_abcdefgijklmnopqrstuvwxyz01234567890" \
https://spotvirtual.com/api/world/cebc47ed-72ab-4522-bbc7-632e5adff627/entity/b81b4dc0-94e6-4771-9ae6-39bcf8941590

The above command should return JSON data similar to the following:

{
"type": 2,
"entityId": "b81b4dc0-94e6-4771-9ae6-39bcf8941590",
"assetId": "7c9f9680-878a-402e-a53c-12766d4b8ed2",
"transform": {
"position": [15.5, 0.004999999999999999, 2.25],
"rotation": [0, 0, 0, 1],
"scale": [1, 1, 1]
},
"eventType": 6,
"userId": "a659f37b-9492-4553-9e5c-10d34351f073",
"clientRev": 262,
"properties": {
"Primary Color": "#c3c3c3"
}
}

Update Entity Properties

We can send a PUT request to the same endpoint to update the entity. For example, to update the Primary Color property, we can run the following:

Use curl to update the Primary Color property:

curl -H "Authorization: Bearer spot_abcdefgijklmnopqrstuvwxyz01234567890" \
-H "Content-Type: application/json" \
-X PUT \
-d '{"properties":{"Primary Color":"#e53e3e"}}' \
https://spotvirtual.com/api/world/cebc47ed-72ab-4522-bbc7-632e5adff627/entity/b81b4dc0-94e6-4771-9ae6-39bcf8941590

The bean bag has now turned red.

Create A New Entity

We can create a copy of the bean bag with the following request. I have changed the position slightly, otherwise the copy would end up in the same position as the original.

curl -H "Authorization: Bearer spot_abcdefgijklmnopqrstuvwxyz01234567890" \
-H "Content-Type: application/json" \
-X POST \
-d '{"type":2,"assetId":"7c9f9680-878a-402e-a53c-12766d4b8ed2","transform":{"position":[18.5,0.004999999999999999,2.25],"rotation":[0,0,0,1],"scale":[1,1,1]},"eventType":6,"userId":"a659f37b-9492-4553-9e5c-10d34351f073","properties":{"Primary Color":"#e53e3e"}}' \
https://spotvirtual.com/api/world/cebc47ed-72ab-4522-bbc7-632e5adff627/entities

The above command should return JSON data similar to the following:

{
"type": 2,
"eventType": 6,
"entityId": "fc2e3b3f-0b52-4f2f-b6ac-2915750692a2",
"userId": "a659f37b-9492-4553-9e5c-10d34351f073",
"assetId": "7c9f9680-878a-402e-a53c-12766d4b8ed2",
"transform": {
"position": [
18.5,
0.004999999999999999,
2.25
],
"rotation": [
0,
0,
0,
1
],
"scale": [
1,
1,
1
]
},
"properties": {
"Primary Color": "#e53e3e"
}
}

There are now two red bean bag chairs.

The response above includes the state of the new entity, including its entityId which was generated by the server.

Delete An Entity

If we don't like the new bean bag then we can delete it with the following request:

curl -H "Authorization: Bearer spot_abcdefgijklmnopqrstuvwxyz01234567890" \
-X DELETE \
https://spotvirtual.com/api/world/cebc47ed-72ab-4522-bbc7-632e5adff627/entity/fc2e3b3f-0b52-4f2f-b6ac-2915750692a2

The command will not print any output if it is successful. The bean bag that we created before should have disappeared from the world.

Endpoints

GET /api/worlds/<worldId>/floorplan

Get the floorplan of the world. At the moment you can’t update the floorplan through the API.

GET /api/worlds/<worldId>/entities

Get a list of all of the entities in the world (including all of the users).

POST /api/worlds/<worldId>/entities

Create a new entity. Requires the world admin scope.

GET /api/worlds/<worldId>/entity/<entityId>

Get a single entity.

PUT /api/worlds/<worldId>/entity/<entityId>

Update an entity.

DELETE /api/worlds/<worldId>/entity/<entityId>

Delete an entity. Requires the world admin scope.

Data objects

World Floorplan

The floorplan has the following shape:

Click to expand example data
{
"height": 6,
"corners": {
"0": {
"x": -21,
"y": 15
},
"1": {
"x": -21,
"y": 37
},
"2": {
"x": 16,
"y": 37
},
"3": {
"x": 16,
"y": 15
},
"0b9441c5-a3b1-448d-85be-be774f075ff8": {
"x": 7,
"y": 37
},
"5ae3c71b-0b95-4051-85d0-fa86fa06b860": {
"x": 7,
"y": 50
},
"6ee6feaa-4a2c-4694-999b-0d8aeae59b6a": {
"x": -24,
"y": 37
},
"85b36252-b679-48eb-83a5-e32d59eae9ff": {
"x": -24,
"y": 50
}
},
"walls": [
{
"corner1": "0",
"corner2": "1",
"frontMaterial": {
"materialId": "1b36d86c-a65d-4532-abb2-86e7539ace62",
"properties": {
"Color": "#1FFF4A",
"diffuseColor": "#9ad5fa"
}
},
"backMaterial": {
"materialId": "1b36d86c-a65d-4532-abb2-86e7539ace62",
"properties": {
"Color": "#1FFF4A",
"diffuseColor": "#9ad5fa"
}
}
},
{
"corner1": "1",
"corner2": "0b9441c5-a3b1-448d-85be-be774f075ff8",
"frontMaterial": {
"materialId": "fb40d5e0-1bb8-4cb4-bdeb-ebb874d03ad1",
"properties": {
"Color": "#1FFF4A",
"diffuseColor": "#fbfbfb"
}
},
"backMaterial": {
"materialId": "faa2c208-2455-4f23-986b-28ea94929c26",
"properties": {
"Color": "#9FDEA6",
"diffuseColor": "#fbfbfb"
}
}
},
{
"corner1": "2",
"corner2": "3",
"frontMaterial": {
"materialId": "1b36d86c-a65d-4532-abb2-86e7539ace62",
"properties": {
"Color": "#1FFF4A",
"diffuseColor": "#9ad5fa"
}
},
"backMaterial": {
"materialId": "1b36d86c-a65d-4532-abb2-86e7539ace62",
"properties": {
"Color": "#1FFF4A",
"diffuseColor": "#9ad5fa"
}
}
},
{
"corner1": "3",
"corner2": "0",
"frontMaterial": {
"materialId": "1b36d86c-a65d-4532-abb2-86e7539ace62",
"properties": {
"Color": "#1FFF4A",
"diffuseColor": "#9ad5fa"
}
},
"backMaterial": {
"materialId": "1b36d86c-a65d-4532-abb2-86e7539ace62",
"properties": {
"Color": "#1FFF4A",
"diffuseColor": "#9ad5fa"
}
}
},
{
"corner1": "1",
"corner2": "6ee6feaa-4a2c-4694-999b-0d8aeae59b6a",
"thickness": 0,
"frontMaterial": {
"materialId": "1b36d86c-a65d-4532-abb2-86e7539ace62",
"properties": {
"Color": "#1FFF4A",
"diffuseColor": "#9ad5fa"
}
}
},
{
"corner1": "6ee6feaa-4a2c-4694-999b-0d8aeae59b6a",
"corner2": "85b36252-b679-48eb-83a5-e32d59eae9ff",
"thickness": 0,
"frontMaterial": {
"materialId": "1b36d86c-a65d-4532-abb2-86e7539ace62",
"properties": {
"Color": "#1FFF4A",
"diffuseColor": "#9ad5fa"
}
}
},
{
"corner1": "85b36252-b679-48eb-83a5-e32d59eae9ff",
"corner2": "5ae3c71b-0b95-4051-85d0-fa86fa06b860",
"thickness": 0,
"frontMaterial": {
"materialId": "1b36d86c-a65d-4532-abb2-86e7539ace62",
"properties": {
"Color": "#1FFF4A",
"diffuseColor": "#9ad5fa"
}
}
},
{
"corner1": "5ae3c71b-0b95-4051-85d0-fa86fa06b860",
"corner2": "0b9441c5-a3b1-448d-85be-be774f075ff8",
"thickness": 0,
"frontMaterial": {
"materialId": "1b36d86c-a65d-4532-abb2-86e7539ace62",
"properties": {
"Color": "#1FFF4A",
"diffuseColor": "#9ad5fa"
}
}
},
{
"corner1": "0b9441c5-a3b1-448d-85be-be774f075ff8",
"corner2": "2",
"frontMaterial": {
"materialId": "fb40d5e0-1bb8-4cb4-bdeb-ebb874d03ad1",
"properties": {
"Color": "#1FFF4A",
"diffuseColor": "#fbfbfb"
}
},
"backMaterial": {
"materialId": "faa2c208-2455-4f23-986b-28ea94929c26",
"properties": {
"diffuseColor": "#fbfbfb"
}
}
}
],
"rooms": [
{
"cornerIds": [
"0b9441c5-a3b1-448d-85be-be774f075ff8",
"5ae3c71b-0b95-4051-85d0-fa86fa06b860",
"85b36252-b679-48eb-83a5-e32d59eae9ff",
"6ee6feaa-4a2c-4694-999b-0d8aeae59b6a",
"1"
],
"id": "e19841af-d56b-4bb0-a057-9631d160acae",
"floorMaterial": {
"materialId": "8d356e1d-f81c-4ead-95cc-2d5f35b16220",
"properties": {
"alpha": "",
"scaleFactor": "4",
"diffuseColor": "#fbfbfb"
}
},
"isOutside": true
},
{
"cornerIds": [
"0",
"3",
"2",
"0b9441c5-a3b1-448d-85be-be774f075ff8",
"1"
],
"id": "7bf0bdf2-b29d-43db-80b6-567d15434ff2",
"floorMaterial": {
"materialId": "4b3971ff-b9cb-4c2a-a854-d3f29006ff8e",
"properties": {
"diffuseColor": ""
}
}
}
],
"floorMaterial": {
"materialId": "1e95cc53-1224-4b13-93c3-2f480b11c4ea",
"properties": {
"Color": "#C3C3C3",
"diffuseColor": "#FECC96"
}
},
"wallMaterial": {
"materialId": "0bcc2b69-3a8d-5ff8-bd13-9b8dc874ad9b",
"properties": {
"Color": "#cdd2cc"
}
},
"exteriorMaterial": {
"materialId": "0bcc2b69-3a8d-5ff8-bd13-9b8dc874ad9b",
"properties": {
"Color": "#888888"
}
},
"wallThickness": 0.32,
"topColor": "#CCEAFC",
"lightDirection": [
0,
-1,
0
],
"lightColor": "#FFFFFF",
"ambientColor": "#999999"
}

World Entity

A world entity has the following shape:

Click to expand example data
{
"type": 2,
"entityId": "b81b4dc0-94e6-4771-9ae6-39bcf8941590",
"assetId": "7c9f9680-878a-402e-a53c-12766d4b8ed2",
"transform": {
"position": [15.5, 0.004999999999999999, 2.25],
"rotation": [0, 0, 0, 1],
"scale": [1, 1, 1]
},
"eventType": 6,
"userId": "a659f37b-9492-4553-9e5c-10d34351f073",
"clientRev": 262, // increments every time a user modifies the entity
"properties": {
// varies depending on the asset
}
}