Stack-chan Matchday exposes an unauthenticated, CORS-open HTTP API for trusted
LAN use. Do not expose device TCP 80, TTS TCP 8787, or watcher setup TCP
8788 to the internet.
GET /healthchecks that the device web service is reachable.GET /api/helpreturns the plain-text command surface accepted byPOST /api/command.GET /api/statusreports the mod version, probability bar, TTS, power, network, mute state, and setup-trigger counters.
Send one command as the raw body of POST /api/command:
pkbar es 62 AA151B be 38 EF3340
balloon temp 8000 Spain scores!
voice favorite-goal Number seven scores!
celebrate goal 170 21 27
celebrate say 170 21 27 Goal!
celebrate result win 170 21 27 Full time
setup show http://stackchan.local/setup
say Hello
mute on 60
mute off
mute status
face happy
look 8 -2
idle look on
light flash 0 85 164
For example:
export STACKCHAN_HOST=stackchan.local
curl --request POST --data-binary "say Matchday ready" \
"http://$STACKCHAN_HOST/api/command"
curl --request POST --data-binary "mute status" \
"http://$STACKCHAN_HOST/api/command"POST /api/control accepts JSON actions for the browser-based control panel
and other structured clients. Device capabilities may vary by mod version, so
clients should check the HTTP response and, when needed, read /api/status
instead of assuming that an action ran.
curl --request POST \
--header 'Content-Type: application/json' \
--data '{"action":"mute","enabled":true,"minutes":60}' \
"http://$STACKCHAN_HOST/api/control"Use GET /api/help on the installed mod as the runtime source of truth for
available plain-text commands.
The device-facing setup surface uses these endpoints under /api/match-setup:
/optionsreceives fixture and standalone-event choices from the watcher./applystores a phone selection as pending./pendinglets the watcher retrieve that selection./ackconfirms success or reports validation failure back to the phone./languageupdates the persisted device language./stylequeues a commentary-style-only update./spoilerqueues a spoiler-protection-only update.
These endpoints form a pending/ack handshake: the phone writes to Stack-chan, the watcher validates and atomically updates its local configuration, and the device displays the acknowledgement. They require HTTP transport.
The device accepts POST /api/match-setup/style with one of casual,
balanced, or professional, for example:
{"commentary_style":"professional"}It forwards the setting through the same pending/ack flow. The watcher-hosted
admin service accepts the same body at POST /api/setup/style.
GET /api/setup/status reports the effective value.
Changing only the style must not reset ESPN event history, market baselines, alert queues, or polling state, and must not replay old commentary. The new style applies to subsequently generated alerts.
The device accepts a strict JSON boolean at POST /api/match-setup/spoiler:
{"spoiler_free_mode":true}It relays the preference through pending/ack. The watcher-local service accepts
the same body at POST /api/setup/spoiler, and GET /api/setup/status reports
the effective spoiler_free_mode value.
Changing only this preference must not reload the selected match or reset ESPN history, market baselines, or polling. Enabling it drops queued Kalshi alerts; confirmed ESPN events continue, while the probability bar and ticker still update silently.
- Use every endpoint only on a trusted LAN; the device API has no authentication and allows CORS.
- Send text commands as UTF-8. Preserve Chinese text rather than translating it before sending it to the device.
- Watcher HTTP delivery should detect failures and back off instead of retrying continuously; device resources are limited.
- Avoid high-frequency status polling while long TTS audio is playing.
- Match Setup and its pending/ack flow require HTTP; serial transport does not provide this workflow.
- When changing an endpoint, update the mod, watcher client, tests, and this guide together.