Skip to content

Code examples

Draw a floor plan GeoJSON using MapLibre

In this demo we use MapLibre GL JS to draw a detailed floor plan in GeoJSON format on the map that were loaded from the REST API.

TIP

If the floor plan is not geo-referenced it will appear at LatLng = [0, 0]
You can geo-reference your floor plan in the Editor

Load the GeoJSON geometry

Use the GeoJSON get request to load the geometries of the floor. Make sure to set the includeAllElements param to include all elements of the layout.

ts
const publishableAccessToken = '<your-token>'
const floorId = '<your-floor-id>'
const endpoint = 'https://api.archilogic.com/v2'
const url = `${endpoint}/floor/${floorId}/geo-json?includeAllElements=true&pubtoken=${publishableAccessToken}`

fetch(url)
  .then(res => res.json())
  .then(drawMap)
  .catch(console.error)

Create the map

Create your maplibre gl instance, with or without a map layer.

ts
import 'maplibre-gl/dist/maplibre-gl.css'
import maplibregl from 'maplibre-gl'

const container = document.getElementById('map')
const map = new maplibregl.Map({
  // optionally add a map layer
  container,
  center: [0, 0],
  zoom: 19,
  maxZoom: 25,
  maplibreLogo: false
})

Draw the GeoJSON on the map

To draw the GeoJSON features on the map, add it as a GeoJSON source and use separate layers to draw shapes and lines. The mapLibre style spec offers lots of options to either map to the default styles or adjust styling, depending on feature parameters.

ts
function drawMap(geoJson) {
  const floor = geoJson.features.find(feature => feature.properties.resourceType === 'Floor')
  map.setCenter(floor.properties.origin)
  map.addSource('floorPlan', { type: 'geojson', data: geoJson })

  // Add fills and lines, using the included 'simplestyle' styles from the geojson features
  map.addLayer({
    id: 'fills',
    type: 'fill',
    source: 'floorPlan',
    paint: {
      'fill-color': [
        // Apply a custom fill to spaces with certain property values
        'match',
        ['get', 'program'],
        'work',
        '#54c072',
        'meet',
        '#ffab00',
        // Default use the give fill color
        ['get', 'fill']
      ]
    }
  })

  map.addLayer({
    id: 'lines',
    type: 'line',
    source: 'floorPlan',
    paint: { 'line-color': ['get', 'stroke'] }
  })
}

Update a layout via the operations API

With the following examples we explore the usage of the layout operations endpoint which allows updating or creating nodes in a layout. Each call will create a new layout revision based on the latest published revision.

It requires floor:update scope.

WARNING

This endpoint is in beta stage. Breaking changes need to be expected.

SpaceUpdate

Update the attributes of a space node

Type

ts
type SpaceUpdateOperationJson = {
  type: 'operation:spaceUpdate'
  nodeId: string
  value: {
    name?: string
    customId?: string
  }
}

Example

Update the custom id of a space

ts
const operations = [
  {
    type: 'operation:spaceUpdate',
    nodeId: '<space-id>',
    value: {
      customId: 'ABC-123'
    }
  }
]

const authorization = `AL-Secret-Token ${secretToken}`

await fetch(`https://api.archilogic.com/v2/layout/:layoutId/operations`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    authorization
  },
  body: JSON.stringify({ operations })
})

ElementUpdate

Type

ts
type ElementUpdateOperationJson = {
  type: 'operation:elementUpdate'
  nodeId: string
  value: {
    name?: string
    customId?: string
    position?: [number, number, number] // [x, y, z] right handed coordinate system, y is up
    rotation?: number // rotation in degrees around the y axis
    product?: string
  }
}

Example

Change the product definition for one asset and the position for another

ts
const operations = [
  {
    type: 'operation:elementUpdate'
    nodeId: '<asset-id-1>'
    value: {
      product: '<new-product-id>'
    }
  },
  {
    type: 'operation:elementUpdate'
    nodeId: '<asset-id-2>'
    value: {
      position: [2.5, 0, 0]
    }
  }
]

const authorization = `AL-Secret-Token ${secretToken}`

await fetch(`https://api.archilogic.com/v2/layout/:layoutId/operations`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    authorization
  },
  body: JSON.stringify({ operations })
})

ElementCreate

Place a new asset element at a given position

Type

ts
type ElementCreateOperationJson = {
  type: 'operation:elementCreate'
  value: {
    type: 'element:asset'
    id: string
    name?: string
    customId?: string
    position: [number, number, number] // [x, y, z] right handed coordinate system, y is up
    rotation?: number // rotation in degrees around the y axis
    product: string
  }
}

Example

Create a desk and a chair. Product geometries are facing z+. Make sure each new element gets a newly created uuid v4.

ts
const operations = [
  {
    type: 'operation:elementCreate'
    value: {
      type: 'element:asset',
      id: '<new-uuid>',
      position: [0, 0, 0],
      product: '<desk-product-id>'
    }
  },
  {
    type: 'operation:elementCreate'
    value: {
      type: 'element:asset',
      id: '<new-uuid>',
      position: [0, 0, 0.6], // move the desk in front of the desk
      rotation: 180, // make the chair face the desk
      product: '<chair-product-id>'
    }
  }
]

const authorization = `AL-Secret-Token ${secretToken}`

await fetch(`https://api.archilogic.com/v2/layout/:layoutId/operations`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    authorization
  },
  body: JSON.stringify({ operations })
})

Access private resources from front end

The following example demonstrates how to access a private floor from the front end using temporary access tokens and the floor plan engine.

Get the temporary access token

Create an API on your back-end to retrieve temporary access tokens

js
app.post('/api/get-access-token', async (req, res) => {
  // https://developers.archilogic.com/space-api/v2/introduction.html#temporary-access-token
  const apiUrl = 'https://api.archilogic.com/v2/temporary-access-token/create'
  const { body } = await got.post(apiUrl, {
    headers: {
      Authorization: `AL-Secret-Token ${process.env.SECRET_TOKEN}`
    },
    json: {
      scopes: [{ resource: 'floor', action: 'readPrivate' }],
      durationSeconds: 3600
    },
    responseType: 'json'
  })
  res.send(body)
})

Use the temporary access token

Make your front end call that API and use the token then via the loadScene method

js
function getTemporaryAccessToken() {
  return fetch(`/api/get-access-token`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      scopes: [{ resource: 'floor', action: 'readPrivate' }]
    })
  }).then(response => response.json())
}
// authorization contains the temporary access token
// expiresAt can be used to check on when you need to request an new token
const { authorization, expiresAt } = await getTemporaryAccessToken()
const floorId = 'bc78475e-0236-4b8d-9d7e-b4f46cd3f6fa'
const container = document.getElementById('hello-plan')
const floorPlan = new FloorPlanEngine({ container })
await floorPlan
  .loadFloorById(floorId, { temporaryAccessToken: { authorization, expiresAt } })
  .catch()

Setup webhooks

Webhooks are available from the following API endpoints: https://api.archilogic.com/v2/webhook

Before using webhooks, a destination endpoint must be set up which supports POST requests from the Archilogic domain.

Currently webhooks are supported for 2 resources: floor with available actions

ts
type FloorAction = 'created' | 'updated' | 'deleted' | 'archived' | 'unarchived'

and order with available actions

ts
type OrderAction = 'created' | 'rejected' | 'completed'

Webhook payload example:

ts
{
    "type": "event",
    "url": "https://webhook.site/179b5241-ab4f-42df-bdb4-7f3154c9177a",
    "resource": "floor",
    "action": "created",
    "createdAt": "2023-11-22T13:44:10.255Z",
    "data": {
      "id": "abaaea05-5070-4c77-bd6c-4f26c5b71340"
     }
}

Create webhooks

Webhook objects must include the following required fields:

ts
{
  active: boolean // webhook state
  action: WebhookActions // FloorAction | OrderAction
  resource: WebhookResources // 'floor' | 'order'
  url: string // format like 'https://{your_destination_url}'
}

Example:

ts
const authorization = `AL-Secret-Token ${secretToken}`
await fetch(`https://api.archilogic.com/v2/webhook`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    authorization
  },
  body: JSON.stringify({
    active: true,
    action: 'updated', // FloorAction | OrderAction
    resource: 'floor', // 'floor' | 'order'
    url: 'https://example.com'
  })
})

Get all webhooks

Example:

ts
const authorization = `AL-Secret-Token ${secretToken}`
const webhooks = await fetch(`https://api.archilogic.com/v2/webhook`, {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    authorization
  }
})

Get webhook by ID

Url path parameter :webhookId can be taken from the GET request.

ts
const webhook = await fetch(`https://api.archilogic.com/v2/webhook/:webhookId`, {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    authorization
  }
})

Update webhooks

Any of the webhook object's parameters could be passed to the request body.

Url path parameter :webhookId can be taken from the GET request.

Example:

ts
const authorization = `AL-Secret-Token ${secretToken}`
// Deactivate webhook
await fetch(`https://api.archilogic.com/v2/webhook/:webhookId`, {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
    authorization
  },
  body: JSON.stringify({
    active: false
  })
})
// Change webhook destination url
await fetch(`https://api.archilogic.com/v2/webhook/:webhookId}`, {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
    authorization
  },
  body: JSON.stringify({
    url: 'https://example1.com'
  })
})

Delete webhooks

Url path parameter :webhookId can be taken from the GET request.

Example:

ts
const authorization = `AL-Secret-Token ${secretToken}`

await fetch(`https://api.archilogic.com/v2/webhook/:webhookId`, {
  method: 'DELETE',
  headers: {
    'Content-Type': 'application/json',
    authorization
  }
})