Build on DigiMaps: a wayfinding API, live channel, webhooks and indoor map embeds.

DigiMaps has a documented REST API with 340+ operations, a Server-Sent Events channel that pushes closures and emergencies to any screen, HMAC-signed webhooks, and a map you can embed and drive with postMessage. Native mobile SDKs are not built yet, and the JavaScript SDK is available on request rather than on npm.

OpenAPI 1.0.0 340+ operations Signed webhooks SSE with replay
Terminal · one kiosk listening text/event-stream
$ MAPS=https://maps.wayvale.example
$ curl -N $MAPS/api/v1/public/venues/wayvale-general/live

retry: 3000

id: 1792818717412-0
event: snapshot
data: {"type":"snapshot","items":[…],"overlay":{…}}

id: 1792818902077-0
event: closure
data: {"type":"closure","action":"upsert","item":{…}}

event: ping
data: {"type":"ping","server_time":"2026-10-24T05:15:17Z"}
A closure arrives a few minutes after connecting. Payloads trimmed.

Five interfaces, all reading the same published map.

Everything reads the same release that kiosks, phones and signage show, so your own screen never disagrees with the kiosk beside it. Versions travel in an X-API-Version header, deprecations come with RFC 8594 headers, and our build checks the published OpenAPI reference against the code.

Surface Use it for Auth Starts at
REST API Read venues, places, levels and routes. Manage maps, live content and kiosks with a Studio account. None for published public data. Studio sign-in for management. API keys for the partner endpoints. /api/v1/… (OpenAPI 1.0.0)
Live channel Push closures, notices, emergencies and new releases to screens you build. None. Published venues only, never staff-only items. GET /api/v1/public/venues/{ref}/live
Signage feeds Third-party signage players that read a feed instead of opening a page. None …/signage.rss · …/signage.json · …/events.ics
Webhooks Tell your paging, ticketing or building systems that something happened. HMAC-SHA256 signature on every delivery POST /api/v1/webhooks
Embeds Put the map, a directory board or a signage page into your website, intranet or player. postMessage to and from the exact parent origin /v/{venue} · /embed/{venue}/board · /signage/{venue}

Read a venue. Ask for a step‑free route.

Public endpoints take a venue’s id or slug and answer only for published venues. Routes use the same six profiles as the kiosk and the live state at the moment you ask.

  • Profiles: standard, wheelchair, reduced_mobility, avoid_stairs, stroller, low_vision
  • A closed destination comes back as destination_closed, with the new place if it moved
  • Hospital and government venues refuse routes through staff-only corridors. Elsewhere they come back flagged as escorted routes (uses_restricted)
  • Evacuation routes to the nearest reachable exit have their own endpoint, and need approved exit data
venue-and-route.sh Shell
MAPS=https://maps.wayvale.example
VENUE=$MAPS/api/v1/public/venues/wayvale-general

# Public endpoints serve published venues only. No key needed.
curl -s $VENUE

# Wheelchair route from the main entrance to Cardiology.
# Live closures apply when you ask, not when the map was published.
curl -s "$VENUE/route?profile=wheelchair\
&from_unit_id=$ENTRANCE&to_unit_id=$CARDIOLOGY"
200 OK Example response, trimmed
{
  "distance_m": 68.4,
  "estimated_time_s": 92,
  "instructions": [ … ],
  "transitions": [ … ],
  "destination_closed": false,
  "relocated_to_unit_id": null,
  "escort_required": false
}

One stream per screen, with replay after the Wi-Fi drops.

The live channel opens with a snapshot of what is active now, then sends each change as it happens. After a reconnect the browser sends Last-Event-ID and the server replays the gap, or sends a fresh snapshot if the gap is too long. Filter by zone or kiosk_id so a screen only gets what was meant for it.

  1. On connect event: snapshot Everything live right now, the routing overlay and the current release.
  2. 10:42 event: closure Level 1 restrooms closed for cleaning. The overlay comes with it, so routes avoid them.
  3. Quiet event: ping Sent after 15 s with nothing else, so proxies keep the stream open.
  4. Wi-Fi drops no connection A notice is posted while this screen is offline.
  5. Reconnect event: notice The browser sends Last-Event-ID. The missed notice is replayed first.
  6. Caught up event: resumed Replay done, without a full reload. After a long gap the server sends a fresh snapshot instead.
  7. 11:05 event: release_published A new map release went live in Studio. Refetch the venue.
One kiosk’s stream from GET /api/v1/public/venues/{ref}/live. Times are an example.
live-screen.js Browser
const MAPS = 'https://maps.wayvale.example';

// One zone's live content. EventSource reconnects by itself and
// sends Last-Event-ID, so the server replays what this screen missed.
const live = new EventSource(
  `${MAPS}/api/v1/public/venues/wayvale-general/live?zone=east-wing`
);

// Overlays are versioned. Keep the highest, so a late delta
// can never reopen a closure.
let overlay = { version: 0 };
const keepNewest = (next) => {
  if (next && next.version > overlay.version) overlay = next;
};

live.addEventListener('snapshot', (e) => {
  const state = JSON.parse(e.data); // live items, overlay, release
  showItems(state.items);
  keepNewest(state.overlay);
});

for (const type of ['notice', 'closure', 'emergency']) {
  live.addEventListener(type, (e) => {
    const delta = JSON.parse(e.data); // action: 'upsert' or 'remove'
    applyDelta(delta);
    keepNewest(delta.overlay);
  });
}

live.addEventListener('release_published', () => refetchVenue());

Polling instead of a stream

Poll /live-state, /notices, /events or /signage with If-None-Match. Unchanged content answers 304.

Feeds for signage players

Point it at signage.rss (RSS 2.0 with Media RSS), signage.json (JSON Feed 1.1) or events.ics (iCalendar), each with ?lang=.

Maps and live notices on your signage players How closures and emergency mode work

A signed webhook when a kiosk drops off or an emergency starts.

Subscribe a URL to the events you need, such as a paging system for emergency.broadcast or a facilities ticket for kiosk.offline. Each delivery is signed with the subscription’s secret, which DigiMaps shows you once, when you create it.

server.js Node.js
import express from 'express';
import { createHmac, timingSafeEqual } from 'node:crypto';

// Shown once, when you create the subscription. Keep it secret.
const secret = process.env.DIGIMAPS_WEBHOOK_SECRET;

function isFromDigiMaps(rawBody, header = '') {
  const expected = 'sha256=' +
    createHmac('sha256', secret).update(rawBody).digest('hex');
  return header.length === expected.length &&
    timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}

// Verify the raw bytes, before any JSON parsing.
const raw = express.raw({ type: 'application/json' });
const app = express();

app.post('/hooks/digimaps', raw, (req, res) => {
  if (!isFromDigiMaps(req.body, req.get('X-Digimaps-Signature'))) {
    return res.sendStatus(401);
  }
  const event = req.get('X-Digimaps-Event'); // e.g. 'kiosk.offline'
  const body = JSON.parse(req.body);

  if (event === 'emergency.broadcast') notifySecurityDesk(body);
  if (event === 'kiosk.offline') openFacilitiesTicket(body);

  res.sendStatus(204); // any 2xx counts as delivered
});
Retries after a failure
  1. 1 s
  2. 5 s
  3. 30 s
  4. 5 min
  5. 30 min
  6. delivery log, redrive by hand

Receivers on loopback, link-local and cloud metadata addresses are always refused, so a webhook cannot be pointed back into the server.

Webhook events you can subscribe to
Event Fires when
venue.published A new map release is live on every screen
venue.review_submitted Someone sent a change for review
venue.review_approved A reviewer approved it. venue.published follows
venue.review_rejected A reviewer sent it back, with a note
comment.created A comment was posted on the map in Studio. The payload carries its text
emergency.broadcast An emergency started, changed or ended
search.missed A visitor searched and found nothing
route.calculated A visitor asked for a route
kiosk.offline A kiosk crossed the offline threshold
kiosk.online That kiosk is back
webhook.test The test button in Studio

Embed the indoor map, then drive it from your page.

The map runs in an iframe and talks to your page with postMessage, only to and from the exact origin it was given. Your page can open a place, change the floor or start a route. The map tells you when it is ready, what was tapped and which route was drawn.

patient-portal.html HTML
<div id="map-slot" style="height:640px"></div>

<script>
  const MAPS = 'https://maps.wayvale.example';

  const src = new URL('/v/wayvale-general', MAPS);
  src.searchParams.set('parent_origin', location.origin);

  const map = document.createElement('iframe');
  map.title = 'Wayvale General Hospital map';
  map.src = src;
  map.style.cssText = 'width:100%;height:100%;border:0';
  document.getElementById('map-slot').append(map);

  const send = (msg) => map.contentWindow.postMessage(msg, MAPS);

  window.addEventListener('message', (e) => {
    // Only the map frame, only from its exact origin.
    if (e.origin !== MAPS || e.source !== map.contentWindow) return;

    if (e.data.type === 'ready') {
      send({ type: 'select_unit', unit_id: CARDIOLOGY });
    }
    if (e.data.type === 'unit_selected') {
      updateSidebar(e.data.unit_id);
    }
  });
</script>

The message contract

Your page to the map
navigate select_unit set_floor set_theme
The map to your page
ready unit_selected route_calculated analytics digimaps:load

analytics forwards each tracked tap, so a signage player can keep its own proof-of-play log. Typed search text is left out unless the venue opts in.

A directory board (/embed/{venue}/board) and a signage page (/signage/{venue}) embed the same way.

Feed in positions from your own beacons or SDK

DigiMaps accepts external position feeds through a documented API: a direct call, a postMessage from the parent page or a DOM event. We have not validated any positioning provider on a real venue yet, so the map is strict about what it trusts.

  • Fixes snap to the walking graph within 8 m
  • A fix expires after 15 s without an update
  • Guidance uses a fix only at 3 m or better (2 m in the hospital profile). Anything worse shows as degraded
What indoor positioning can and can’t do today
kiosk-shell.js Position API
// Runs in the map's own window: a kiosk shell, a WebView,
// or the SDK of your positioning system.
window.digimaps.setPosition(
  { lat: 28.6139, lng: 77.209, level: 1 }, // WGS84 and floor
  92,   // heading, degrees from true north (optional)
  1.8,  // accuracy in metres (optional)
  'ble' // source label (optional)
);

// Plan coordinates work too: { x: 1234, y: 567, zn: 1 }

// From the parent page:
//   postMessage({ type: 'digimaps:position', position }, MAPS)
// From any script on the page:
//   dispatchEvent(new CustomEvent('digimaps:position',
//     { detail: { position } }))

window.digimaps.clearPosition(); // back to "You are here"
Studio Admin API keys

Signage integrator · lobby screens

Xq7mP2aL.r9KdW4tVn2••••••••••••••••••••••••

This is the only time the full key is shown. DigiMaps keeps the prefix and a bcrypt hash of the rest.

Scopes
readwritepublishanalyticsfeeds
Venues
Wayvale General Hospital only
Expires
Never30 days90 days1 year
Example key. Rotating it issues a new secret, shown once again.

API keys that can only do what you allowed.

Partner API keys belong to your organisation and carry no user session. Each one has its own scopes, venues and expiry, and every request is checked against them.

Send it as
X-API-Key: prefix.secret or Authorization: Bearer …
Scopes
read, write, publish, analytics, feeds, plus an optional venue allow-list
Stored as
An 8-character prefix and a bcrypt hash. The full key is shown once
Lifetime
Never expires, 30 days, 90 days or 1 year. Rotate or revoke at any time
Partner API
/partner/whoami, /partner/venues and anonymous visitor events per venue

What you can’t build on yet.

Check this list before you scope an integration. If one of these blocks your project, tell us at the start and we will say plainly whether it is on our roadmap.

If you need an indoor map SDK for your own app, today that means the iframe and JavaScript API above.

Developer features that are not available yet
Native iOS and Android SDKs Not built. On the roadmap. A blue dot on iPhone would need one.
JavaScript SDK on npm Not published. Version 0.3.0 (plain JavaScript, a React component and a web component) is shared on request.
Public sandbox and hosted reference Not yet. We send the OpenAPI reference file to your developers.
Ready-made connectors None ship. The Studio catalogue holds sample items only. Use webhooks and the API.
A validated positioning provider None yet. The position API accepts fixes from the system you choose.

Questions developers ask us

Security reviewers usually want our trust and evidence page next.

Is there a DigiMaps SDK on npm?

Not yet. The JavaScript SDK, version 0.3.0, is unreleased and shared on request. It offers a plain JavaScript mount, a React component and a web component, and all three wrap the same iframe and postMessage contract, so a plain iframe works today.

Do you have native iOS and Android SDKs?

No. Native mobile SDKs are on our roadmap, not available. Today you can load the web map in a WebView, and a native app or kiosk shell can feed positions to it with window.digimaps.setPosition.

How do we get an API key?

An administrator creates partner API keys in Studio under Admin, API keys. Each key has scopes (read, write, publish, analytics, feeds), an optional list of venues and an expiry of never, 30 days, 90 days or one year. The full key is shown once; DigiMaps stores only its prefix and a bcrypt hash.

Can our screens get live updates without polling?

Yes. The live channel is a Server-Sent Events stream per venue, filtered by zone or kiosk. It opens with a snapshot, sends deltas for notices, closures, emergencies and new releases, and replays missed events after a reconnect. JSON polling endpoints with ETags exist for players that cannot hold a stream open.

How do we check that a webhook really came from DigiMaps?

Every delivery carries an X-Digimaps-Signature header: sha256= followed by the HMAC-SHA256 of the raw request body, keyed with the subscription secret. Compute the same value and compare it in constant time. Failed deliveries retry after 1 s, 5 s, 30 s, 5 min and 30 min, then wait in the delivery log for a redrive.

Can we feed in our own indoor positioning?

Yes. Any BLE, UWB or visual positioning SDK can send fixes through window.digimaps.setPosition, an exact-origin postMessage or a DOM event. Fixes snap to the walking graph within 8 m and expire after 15 s. A fix is used for turn-by-turn guidance only when it reports 3 m or better (2 m in the hospital profile).

Walk through the API with an engineer

Bring the system you want to connect: a patient portal, a signage CMS, a building management system. We will show the calls, the events and the limits, and send you the OpenAPI reference.