Device tokens, public links, and ingest
Three credential surfaces that aren't user sessions: device tokens for boards and gateways, capability tokens in public URLs, and API-key-authenticated ingest.
Device tokens
Boards, kiosks, and sensor gateways are devices — non-user identities with their own long-lived token. Admins manage them:
GET/POST /orgs/{orgId}/devices (+ PUT /{id}) — admin
POST /orgs/{orgId}/devices/{id}/pair — mint a short-lived 6-char pairing code
POST /orgs/{orgId}/devices/{id}/cast — push content (e.g. a recipe) to the screen
The screen claims the code (rate-limited, 10/min/IP):
POST /devices/pair
{ "code": "K7M2QX" }
The response contains the device token (mdt_…) — shown once, stored hashed. The device then authenticates with the x-device-token header:
GET /device/state
x-device-token: mdt_...
{
"device": { "id": "51f8a234-…", "name": "Hot line wallboard", "kind": "wallboard_boh", "config": {} },
"org": { "name": "Riverbend Senior Living", "brand": { "primary": "#283040", "accent": "#F36744" } },
"site": { "id": "9b80fa65-…", "name": "Riverbend — Columbus", "timezone": "America/New_York" },
"date": "2026-08-08",
"serverTime": "2026-08-08T20:39:12.413Z",
"cast": null,
"production": [ ... ],
"alerts": [ { "kind": "task_missed", "severity": "warning", "message": "Missed: …" } ],
"handoffs": []
}
The payload adapts to the device kind — production timers and alerts for kitchen wallboards, the day-part menu for menu boards, the tray queue for tray-line screens. date is computed in the site's timezone.
Realtime: devices may also open a WebSocket at GET /board/ws?token=<device token>. Any received frame means "refetch /device/state now" — frames are hints, not data, and boards must keep working on polling alone if the socket drops. Board-side images are served via GET /board/media/content/{key} with the device token (the regular media routes require a user session).
Device counts meter against the plan — pairing beyond the cap returns the 402 shape with feature: "device_limit".
Public token links
Some URLs are themselves the credential — sanitized, rate-limited, no login:
GET /survey/{token} — a survey invite (questions + branding)
POST /survey/{token}/submit — submit answers (validated server-side)
GET /share/q/{token} — a shared catering quote
GET /share/i/{token} — a shared catering invoice
GET /share/insp/{token} — a shared inspection report
Responses expose display data only — never organization ids or internal linkage. Treat these tokens as bearer capabilities: anyone with the URL can view, and reissuing a share rotates the token. Public surfaces are rate-limited per IP (see rate limits).
There is also a public support endpoint used by this site's contact form:
POST /support-inquiry — {name, email, org?, topic, message} → 202
Scan deep links (QR tags)
Printed equipment and space tags encode a web deep link, not a token:
https://miseline.keyedsystems.com/scan/{tagCode}
Unlike the public token links above, a tag code is not a credential — it identifies a target but grants nothing. Opening the link signed out bounces through sign-in with the scan target preserved; resolving it requires membership in the organization that owns the tag.
The API behind the page is:
GET /orgs/{orgId}/scan/{tagCode}
Unauthenticated calls return a machine-usable 401 carrying the scan reference, so a client can complete sign-in and resume the exact scan:
{ "error": "Authentication required", "statusCode": 401, "scan": { "tagCode": "GA-7C0A41BD", "orgId": "…" } }
The body is identical whether or not the tag exists — the endpoint never confirms a tag's existence without authentication. Authenticated responses return the resolved target with a role-aware action list and context; see the scan overview for the family.
HL7 ADT ingest
EHR/census systems feed the clinical census over HL7 v2 ADT:
POST /orgs/{orgId}/adt/hl7
x-api-key: mk_live_...
content-type: application/json
{
"siteId": "cb35f458-366f-4aff-916c-cce0674d9421",
"message": "MSH|^~\\&|ADT|Hospital|Miseline|Dietary|20260808120000||ADT^A01|MSG00042|P|2.5\nPID|1||MRN-9042^^^MRN||Doe^Jane||19510402|F\nPV1|1|I|3W^302^A\nAL1|1|FA|^Peanut\nODS|F|||CARDIAC^Cardiac diet"
}
{
"processed": 1,
"results": [
{ "type": "ADT^A01", "outcome": "applied", "detail": { "mrn": "MRN-9042", "action": "admitted", "orderCreated": true } }
]
}
- Auth: an active API key for the same organization via
x-api-key, or a signed-in admin session. Failure behavior, exactly: a wrong, revoked, or other-organization key returns401 {"error": "Invalid API key"}; no key and no session returns401 {"error": "Authentication required"}. ThesiteIdmust belong to the organization (404 Site not foundotherwise). - Events:
A01admit,A02transfer,A08update (upsert demographics, unit/room, allergies, diet codes),A03discharge. A discharge for an unknown MRN is skipped, not an error; messages without a PID-3 MRN are skipped with a reason. - Allergies and diets:
AL1allergies map to structured allergens;ODSdiet codes map where recognized, and anything unrecognized is preserved as unmapped for the diet office to review — nothing is silently dropped. - A body with no parseable MSH-framed message returns
422. Every message is logged to an audit trail either way, and the clinical feature (Pro and Enterprise) must be on the plan.
Multiple messages can be batched in one message string; results reports each separately.