Skip to content

Extension SDK ​

The Extension SDK enables you to create custom logic that can be run inside Editor or headless Worker. It provides easy to use but powerful methods to query, mutate, draw, interact, compute or export a layout.

Check the Setup guide to learn how to work locally and deploy your first extension.

Hosts ​

Editor ​

Editor extensions can provide their own UI, rely on dialogs, or run as headless scripts.

ts
export async function run({ hostApi, container }) {
  const spaces = await hostApi.getSpaces()
  container.innerText = `Space count: ${spaces.length}`
}

Cloud Worker ​

Worker extensions are accessible via an API and can leverage parameters. They are also exposed as tools for your organization by the MCP Server.

ts
export async function run({ hostApi, parameters }) {
  const subCategory = parameters?.subCategory || 'meetingRoom'
  const spaces = await hostApi.getSpaces({ where: { subCategory } })
  return {
    spaceCount: spaces.length,
    subCategory
  }
}
bash
curl -X POST https://api.archilogic.com/v2/floor/:floorId/extensions/:extensionId \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{ "parameters": { "subCategory": "privateOffice" } }'

Host API ​

Every extension exports a run function which is executed by the host in a sandbox. The HostApi instance is provided as an argument which is the main interface for extensions allowing you to run commands that are executed by the host.

While editor extensions can subscribe to events and provide their own UI which is loaded in an iframe, worker extensions need to return something in the run function for the endpoint to capture it.

js
export async function run({ hostApi }) {
  const meetingRooms = await hostApi.getSpaces({
    where: { category: { eq: 'meet' }, seatCapacity: { gte: 4, lte: 6 } }
  })
}
ts
import type { HostApi } from '@archilogic/extension-sdk'

export async function run({ hostApi }: { hostApi: HostApi }) {
  const meetingRooms = await hostApi.getSpaces({
    where: { category: { eq: 'meet' }, seatCapacity: { gte: 4, lte: 6 } }
  })
}

Events ​

Hosts Editor

You can register event handlers for various events at run time

ts
hostApi.on('layout-change', ({ operations }) => {})
hostApi.on('selection-change', ({ selectedNodes }) => {})
hostApi.on('canvas-click', ({ position, nodeId }) => {})
hostApi.on('graphic-drag', ({ position, nodeId }) => {})

Queries ​

Hosts EditorCloud Worker

Query methods have powerful filter options similar to the GraphQL API.
They have the same interface as the Floor plan SDK queries, except being async.

Get elements ​

Query elements with the getElements method by various properties and optionally select the shape of the returned objects.

ts
const largeWindows = await hostApi.getElements({
  where: { type: 'element:window', dimensions: { length: { gte: 3 } } }
})

Get element by id ​

Retrieve specific properties from an element with getElementById

ts
const { dimensions, boundingBox } = await hostApi.getElementById({
  id: '<asset-id>',
  select: { boundingBox: true, dimensions: true }
})

Get spaces ​

Query spaces with the getSpaces method by various properties and optionally select the shape of the returned objects.

ts
const spaces = await hostApi.getSpaces({
  where: { seatCapacity: { gte: 5 } }
})

Get space by id ​

Retrieve specific properties from a space with getSpaceById

ts
const { labelPoint, contour, elements } = await hostApi.getSpaceById({
  id: '<space-id>',
  select: { labelPoint: true, contour: true, elements: true }
})

Get products ​

Query products with the getProducts method by various properties and optionally select the shape of the returned objects.

ts
const chairCounts = await hostApi.getProducts({
  select: { id: true, count: true },
  where: { subCategory: 'taskChair' }
})

Get layout ​

Retrieve properties of the current layout with getLayout. A common use case is reading the overall boundingBox to compute the floor extents.

ts
const { id, name, boundingBox } = await hostApi.getLayout({
  select: { id: true, name: true, boundingBox: true }
})

Get floor ​

Retrieve metadata for the current floor with getFloor — id, name, level, area, labels, transform and address/coordinates.

ts
const { id, name, location } = await hostApi.getFloor({
  select: { id: true, name: true, location: true }
})

Operations ​

Hosts Editor

Make changes to the layout, like adjusting space meta data or placing assets inside a space. This interface mirrors the operations endpoint.

Create ​

Create elements in the layout.

ts
await hostApi.runOperations({
  operations: [
    {
      type: 'operation:elementCreate',
      value: {
        type: 'element:asset',
        position: [-2, 0, 3],
        rotation: 45,
        product: '<product-id>'
      }
    }
  ]
})

Update ​

Update the layout by changing node's properties or creating/removing nodes.

Like the custom attributes of a space.

ts
await hostApi.runOperations({
  operations: [
    {
      type: 'operation:spaceUpdate',
      nodeId: '<space-id>',
      value: { customAttributes: { isBooked: true } }
    }
  ]
})

Delete ​

Remove elements from the layout.

ts
await hostApi.runOperations({
  operations: [
    {
      type: 'operation:elementRemove',
      nodeId: '<element-id>'
    }
  ]
})

Drawing ​

Hosts Editor

Add plan layer ​

ts
const layerRef = await hostApi.addPlanLayer({ id: 'my-layer' })

Add plan graphics ​

ts
const layerRef = await hostApi.addPlanGraphic({
  shapes: [
    {
      type: 'curve:circle',
      radius: 1,
      position: [1, 0]
    }
  ],
  layerId: 'my-layer'
})

Interactive graphics ​

Make shapes draggable or clickable with the interaction option. fixedScreenSize keeps the shape at a constant pixel size regardless of zoom — useful for handlers and markers.

ts
const handler = await hostApi.addPlanGraphic({
  layerId: 'orange-handlers',
  shapes: [{ type: 'curve:circle', radius: 0.5, position: [0, 0], style: { fill: '#f95' } }],
  position: [-2, 5],
  fixedScreenSize: true,
  interaction: { drag: true }
})

hostApi.on('graphic-drag', ({ position, nodeId }) => {
  if (nodeId === handler.id) {
    // react to the drag, e.g. update other graphics
  }
})

Set plan config ​

Controls the visual appearance of the floor plan. theme accepts a FloorPlanTheme, supporting byFilter, byId, and byType styling. Colors in ShapeStyle can be a CSS hex string ('#ff0000'), a hex number (0xff0000), or an RGB array ([255, 0, 0]).

ts
await hostApi.setPlanConfig({
  theme: {
    byFilter: [
      {
        where: { customAttributes: { isBooked: { eq: true } } },
        style: { fill: '#FF8800' }
      },
      {
        where: { customAttributes: { isBooked: { eq: false } } },
        style: { fill: '#00FF88' }
      }
    ]
  }
})

Interact ​

Hosts Editor

Zoom to node ​

ts
await hostApi.zoomToNode({ nodeId: '<space-id>' })

Zoom extents ​

ts
await hostApi.zoomExtents({ margin: 2, animate: true })

Select nodes ​

ts
await hostApi.selectNodes({ nodeIds: ['<space-1>'] })

Dialogs ​

Hosts Editor

Confirm ​

ts
const isConfirmed = await hostApi.confirm({
  title: 'Remove all assets',
  confirmLabel: 'Yes',
  cancelLabel: 'No'
})

Prompt ​

ts
const { format } = await hostApi.prompt({
  title: 'Export format',
  fields: {
    format: {
      label: 'Format',
      type: 'select',
      options: ['JPG', 'PNG'],
      default: 'JPG'
    }
  }
})

Compute ​

Hosts EditorCloud Worker

Run complex tasks like way finding.

Get path ​

Compute the walking path from A to B

ts
const path = await hostApi.getPath({
  start: [3, 4.5],
  end: [25, 123.5]
})

Find closest ​

Find the closest space with seat capacity greater than 4 that is bookable

ts
const path = await hostApi.findClosest({
  start: [3, 4.5],
  where: {
    seatCapacity: { gte: 4 },
    customAttributes: { isBooked: { eq: false } }
  }
})

Exports ​

Hosts EditorCloud Worker

Export the layout including the custom graphics and style to various formats

By default, exports trigger a browser download of the result in editor extensions. Pass skipDownload: true to suppress the download and only receive the result. Worker extensions only support skipDownload: true.

PDF ​

When skipDownload: true, returns an ArrayBuffer.

ts
// triggers browser download (editor only)
await hostApi.exportPdf({
  orientation: 'landscape', // 'landscape' | 'portrait'
  format: 'A4' // 'A4' | 'A3' | 'letter'
})

// skip download and return result directly
const arrayBuffer = await hostApi.exportPdf({
  orientation: 'landscape',
  format: 'A4',
  skipDownload: true
})

SVG ​

When skipDownload: true, returns a string.

ts
// triggers browser download (editor only)
await hostApi.exportSvg()

// skip download and return result directly
const svgString = await hostApi.exportSvg({ skipDownload: true })

DXF Coming soon ​

ts
const path = await hostApi.exportDxf()

GeoJSON Coming soon ​

ts
const path = await hostApi.exportGeoJson()

IMDF Coming soon ​

ts
const path = await hostApi.exportImdf()

IFC Coming soon ​

ts
const path = await hostApi.exportIfc()

GLTF Coming soon ​

ts
const path = await hostApi.exportGltf()