Skip to content

The JSON API

Everything the web interface does has a JSON equivalent. Scripts and integrations can use it to read status, change settings, start jobs and follow events. The command line uses the same API in service mode.

The API is served by the service under /api/v1/, on the same port as the web interface (8790 by default). In local mode, the default, it is plain HTTP on this computer and needs no credentials. In network mode it is HTTPS and needs an API token. See Local mode.

Local mode

A service in local mode listens on this computer only and needs no credentials. Every request acts as the administrator /local. Call it directly:

curl -s http://127.0.0.1:8790/api/v1/overview
  • No credentials. A token or a session cookie is ignored. Do not send one.
  • The Host header must match. It must be localhost, 127.0.0.1 or [::1] with the port the service listens on, or the loopback address --listen names. Any other Host gets status 403 with SiteManager runs in local mode and answers only to localhost, 127.0.0.1 and [::1] on port 8790. (The port in the message is the service's own.)
  • The Origin rule. A change (POST, PUT, PATCH or DELETE) with an Origin header other than http:// plus the Host is refused with status 403 and cross-site request refused (as JSON for an /api/ address). A script that sends no Origin header is not affected.
  • Network-only operations answer 403. The operations for setup, login, logout, users, tokens, sessions and passwords need the login store, which local mode does not have. In the OpenAPI document they carry x-network-only: true. In local mode they answer 403 with {"error": "not available in local mode: SiteManager listens on this computer only and has no logins, users or API tokens; to let other computers connect, restart it with a network --listen address (for example --listen :8790)"}. In the web interface, opening one of those pages redirects to /, and a form post to one gets 403 with the same text.
  • GET /api/v1/me and GET /api/v1/audit still work. /api/v1/me returns the user /local with the role admin.
  • GET /api/v1/version and GET /api/v1/server report "mode": "local" or "mode": "network". In local mode /api/v1/server has no fingerprint.
  • Remote scripts reach a local-mode service only through an SSH tunnel on the same port number, because the Host header carries the port. Do not put a reverse proxy in front of it.

The rest of this page describes network mode, unless it says otherwise.

The API description

The service publishes its own API description as an OpenAPI 3 document. In network mode, download it once you have a token. In local mode leave out the header and use http://127.0.0.1:8790:

curl -sk -H "Authorization: Bearer $SITEMANAGER_TOKEN" https://wallpc:8790/api/v1/openapi.yaml

Each operation in the document names the permission it needs: view, manage, admin or account, or public for an address that needs no login. A viewer has view and account. An administrator has all of them. In local mode the caller is always an administrator.

Signing in (network mode)

Scripts use an API token. Create one on the Account page, or with sitemanager tokens create NAME. The token is shown once. Send it as a bearer token:

export SITEMANAGER_TOKEN=...   # the token from the Account page
curl -sk -H "Authorization: Bearer $SITEMANAGER_TOKEN" https://wallpc:8790/api/v1/overview
  • HTTP Basic authentication is not accepted. The service answers 401 with the message HTTP Basic is not accepted; create an API token on the Account page and send Authorization: Bearer <token>.
  • Tokens do not expire. A user can have up to 100. Revoke one on the Account page or with DELETE /api/v1/tokens/{id}. It stops working on the next request.
  • Browsers use a session cookie set by POST /api/v1/login.
  • Password logins are rate limited, and answer 429 with a Retry-After header when the limit is reached. Requests with a token are not limited. See Sign-in limits.

The certificate

curl -k skips certificate verification. To check the certificate instead, save it and compare its fingerprint with the one in the footer of the web interface:

openssl s_client -connect wallpc:8790 </dev/null 2>/dev/null | openssl x509 > sitemanager.pem
openssl x509 -noout -fingerprint -sha256 -in sitemanager.pem
curl --cacert sitemanager.pem -H "Authorization: Bearer $SITEMANAGER_TOKEN" https://wallpc:8790/api/v1/overview

GET /api/v1/server returns the version and the fingerprint after you have signed in.

No sign-in needed

Two addresses answer without a login so that a monitoring system can use them:

  • /healthz, a plain health check;
  • GET /api/v1/version, the service version.

The sign-in address (POST /api/v1/login) and the first-run setup address (POST /api/v1/setup) are open as well, because they have to be.

What the API covers

Area Paths
Account /api/v1/me, /api/v1/tokens, /api/v1/password, /api/v1/sessions
Users and audit /api/v1/users, /api/v1/audit?limit=N (1 to 1000, 100 by default)
Displays and walls /api/v1/overview, /api/v1/displays, /api/v1/walls, /api/v1/discovery/broadcast, /api/v1/discovery/sweep
Settings and tracker /api/v1/settings/registry, /api/v1/settings/{group}, /api/v1/settings/save, /api/v1/settings/discard, /api/v1/tracker
Actions and jobs /api/v1/actions/reboot, /api/v1/actions/calibrate, /api/v1/actions/identify, /api/v1/idle, /api/v1/jobs
Firmware /api/v1/firmware/catalogue, /api/v1/firmware/cache, /api/v1/firmware/rollouts
Walls, rooms and files /api/v1/walls/{id}/layout, /api/v1/rooms, /api/v1/host, /api/v1/config, /api/v1/touch
Monitoring /api/v1/monitor, /api/v1/history/..., /api/v1/alerts, /api/v1/drift, /api/v1/capabilities
Profiles /api/v1/profiles
Support /api/v1/diagnostics/bundle

In local mode, /api/v1/tokens, /api/v1/password, /api/v1/sessions and /api/v1/users answer 403, as described under Local mode. /api/v1/me and /api/v1/audit work in both modes.

Display security has its own routes: GET /api/v1/access, PUT /api/v1/access/policy, POST /api/v1/access/secure, /api/v1/access/change and /api/v1/access/release, POST /api/v1/displays/{serial}/access/trust, and DELETE /api/v1/displays/{serial} with releaseFirst=true or keepLocked=true; for SSH keys, GET /api/v1/displays/{serial}/ssh, POST /api/v1/ssh-keys, /api/v1/ssh-keys/remove and /api/v1/ssh-keys/check, DELETE /api/v1/displays/{serial}/ssh/password-login and POST /api/v1/displays/{serial}/ssh/review; and for the update channel, GET /api/v1/displays/{serial}/update-channel, POST /api/v1/update-channel and /api/v1/update-channel/check. GET /api/v1/firmware/watch lists the displays to check again after a firmware update (needs only the view role): watches, each with serial, name, expected, previous, due, created, jobID and state (trial, confirmed or unknown). A display in GET /api/v1/displays has firmwareBoot (trial or confirmed, left out when unknown) and firmwareRecheck (the time of the next check, left out when nothing is watched). A display that is no longer in the site is left out of the list. The diagnostics bundle takes include (canvus, canvus-server, showcase, launcher, crash-dumps) to add files of the MultiTaction products from the computer the service runs on; only an administrator can include crash-dumps. An access key is never in any answer. See Display security.

The OpenAPI document lists every path, its parameters and its answers.

Events

Three streams of server-sent events let a program follow changes without polling. Read them with an EventSource client or a streaming HTTP client:

  • GET /api/v1/events: display status;
  • GET /api/v1/jobs/events: jobs;
  • GET /api/v1/alerts/events: alerts.

A stream ends when the token that opened it is revoked.

Errors

Errors are JSON: {"error": "..."}. A 409 for a display that is busy in a job also carries "job", the id of that job.

Some changes use optimistic locking. Layouts, rooms, profiles, the host settings and alert settings return an ETag. If you send it back in an If-Match header with your change, SiteManager refuses the change with 409 when someone else changed the same thing in the meantime. Without the header the last write wins.

A POST, PUT, PATCH or DELETE request that carries an Origin header other than the service's own address is refused with status 403 and the text cross-site request refused, in both modes. In network mode the service's own address is https:// plus the Host, and in local mode it is http:// plus the Host. A script that sends no Origin header is not affected.