API reference
SQ Manager runs an HTTP server on the Android device you install it on. The dashboard, the ticket kiosk, the queue display and the workstation all talk to that server through a small JSON over HTTP API. This page documents the public endpoint shape so you can write a custom display, a third-party reporting tool, or a kiosk skin against it.
On this page
Base URL & conventions
The default port is 8443 on the device that runs the app. The base URL therefore looks like:
http://192.168.0.42:8443/
You can change the port in the in-app Settings → Virtual Server screen. The same host serves the dashboard HTML at / and the API under the prefixes below. All API responses are application/json; charset=utf-8 unless documented otherwise. Field names use camelCase. Timestamps are ISO 8601 strings in the device's local time zone.
Authentication
Every endpoint that reads queue data, calls the next ticket, or modifies settings requires an authenticated dashboard session. The default auth flow is:
POST /read/loginwith a JSON body{"username": "...", "password": "..."}. On success, the response sets a session cookie.- The browser (or your script) keeps the cookie and re-uses it on every subsequent call.
- Idle sessions expire after 30 minutes of no activity.
A small number of endpoints are exempted from the login requirement because they are needed before the login screen can render (for example, the language list and the build version). See Exempted endpoints below.
Endpoint groups
The server distinguishes five route groups by URL prefix. The prefix tells the server which handler to dispatch to and which response shape to use.
/read/ - reads
Read-only lookups. GET by default; some accept POST for backward compatibility with the dashboard's older XHR wrapper.
/read/login-setting
GET /read/login-setting
Returns the public, non-secret parts of the login screen config: available languages, app build, device nickname, allowed-username hint.
/read/login
POST /read/login
Authenticates a dashboard user. Body: {"username": "string", "password": "string"}. On success returns {"ok": true, "displayName": "...", "permissions": ["VIEW","CALL","..."]} and sets a session cookie. On failure returns 401 with {"ok": false, "reason": "invalid_credentials"}.
/read/queue-display-setting
GET /read/queue-display-setting
Returns the queue-display screen configuration: theme, marquee text, language pair, font size, idle screen on/off.
/read/ticket-kiosk-setting
GET /read/ticket-kiosk-setting
Returns the ticket-kiosk configuration: service list (with English / Bahasa Malaysia labels), printer selection, footer text, idle timeout.
/read/workstation-setting
GET /read/workstation-setting
Returns the workstation (counter) configuration: counter list, services this counter serves, the "next" call strategy (FIFO / priority / VIP).
/read/web-socket-port
GET /read/web-socket-port
Returns {"port": 8444}. The dashboard opens a WebSocket on that port for live ticket and call updates.
/trigger/ - state changes
Trigger endpoints perform a side-effect on the device (issue a ticket, call the next one, mark a customer as done, reset the system). They are typically POST and always require an authenticated session.
/trigger/testing
POST /trigger/testing
Diagnostic ping. Body: {"nonce": "..."}. Response: {"ok": true, "echo": "..."}. Used by the dashboard's "is the server alive" check.
/trigger/system-reset
POST /trigger/system-reset
Wipes all live queue state for the current business day (issued tickets, call log, served count). Does not delete configuration or dashboard users. Requires the ADMIN permission. Response: {"ok": true, "resetAt": "2026-10-11T08:00:00+08:00"}.
/trigger/app-version
POST /trigger/app-version
Returns the running versions of every installed SQ Manager module (system, dashboard, virtual kiosk, ticket kiosk, queue display). Used by the in-app "About → Versions" page.
/trigger/update-htdocs
POST /trigger/update-htdocs
Asks the device to download and install a newer copy of a single web component (for example, the dashboard). Body: {"htdocs_type": "dashboard", "download_url": "https://...", "file_name": "..."}. Requires the ADMIN permission. Response is streamed back over the same connection with progress events.
Other trigger endpoints cover the rest of the queue workflow: /trigger/ticket-issue, /trigger/ticket-call, /trigger/ticket-recall, /trigger/ticket-skip, /trigger/ticket-served, /trigger/ticket-no-show, /trigger/ticket-transfer, /trigger/feedback-submit. Each takes a JSON body and returns {"ok": true, ...} or {"ok": false, "reason": "..."}.
/enum/ - enumerations
Returns the fixed enumerations the dashboard needs to render dropdowns: services, counters, departments, ticket prefixes, languages, permission levels, ticket states, and so on. GET only. Responses are short and cacheable on the client.
/datapool/ - shared queue state
The datapool endpoints expose the live, shared state of the queue. They are read by the WebSocket subscriber that the dashboard opens after login and by the queue-display screen. The two you will touch most often are:
/datapool/queue-data- the full snapshot of currently-issued tickets, served tickets, no-shows, and per-counter call log. Returned as a single JSON document and re-sent (in delta form) on every state change./datapool/queue-data/recent- the last N served tickets, for the served-today wall display.
/raw/ - raw assets
Returns a raw binary asset, not JSON. Today the only asset served this way is /raw/voice-module which streams the bundled TTS voice prompt that the workstation plays when a ticket is called. The response is audio/wav or audio/ogg depending on the device locale.
Exempted (no-auth) endpoints
The following endpoints are exempted from the login requirement by BlueprintExceptionApi, so the login screen can render before a user has signed in:
/read/login-setting
/read/login
/trigger/testing
/trigger/system-reset
/trigger/app-version
/trigger/update-htdocs
/read/queue-display-setting
/read/ticket-kiosk-setting
/read/workstation-setting
/read/web-socket-port
/raw/voice-module
/datapool/queue-data
Even though these endpoints are exempted from the access-token check, they still validate input and apply the same permission rules as authenticated calls. /trigger/system-reset and /trigger/update-htdocs in particular still require a logged-in dashboard user with the ADMIN permission - "exempted" here means "exempted from the auth check at the edge", not "open to the public".
Error responses
The server returns standard HTTP status codes plus a small JSON body for errors. Examples:
400 Bad Request {"ok": false, "reason": "missing_field", "field": "username"}
401 Unauthorized {"ok": false, "reason": "invalid_credentials"}
403 Forbidden {"ok": false, "reason": "permission_denied", "need": "ADMIN"}
404 Not Found {"ok": false, "reason": "no_such_endpoint"}
405 Method Not Allowed (plain text)
429 Too Many Requests {"ok": false, "reason": "rate_limited", "retryAfterMs": 1000}
500 Server Error {"ok": false, "reason": "internal", "traceId": "..."}
Versioning
The on-device API does not yet ship with a version prefix. New fields are added to existing response objects in a backward-compatible way (additive only). Breaking changes are signalled by a X-SQM-Api-Version response header that the server starts sending one minor release before the breaking change takes effect; clients that understand the header can refuse to talk to an incompatible server. Until that header starts shipping, the safest assumption is that every release may add fields but will not rename or remove them.
Looking for the dashboard's JavaScript? It lives in app/src/main/assets/initial_dashboard_htdocs/ in the project tree. Looking for a way to subscribe to live updates? Open a WebSocket on the port returned by /read/web-socket-port after login - the same JSON delta format as the REST datapool is sent on every change.