# ProPresenter API, as actually observed Recorded against the church's own machine on 2026-09-06, not from documentation. Re-run `parent-call-probe` to refresh this. ``` Host 10.30.0.2:1025 (the MacBook, "MacBook-Pro") ProPresenter 21.3 Platform mac, macOS 26.6.2 api_version v1 ``` ## Endpoints that exist | Request | Result | | --- | --- | | `GET /version` | `200` + JSON. Note: **not** `/v1/version`, which 404s | | `GET /v1/messages` | `200` + array of messages | | `GET /v1/message/{id}` | `200` + one message | | `POST /v1/message/{id}/trigger` | **`204`**, ~34ms | | `GET /v1/message/{id}/clear` | **`204`**, ~7ms | | `POST /v1/message/{unknown-uuid}/trigger` | `404` | `{id}` accepts either the uuid or the URL-encoded name — both returned `204`. The coordinator uses the uuid, resolved from the name, so that renaming the message in ProPresenter is noticed rather than silently changing which message is triggered. ## The message that already exists The spec assumed a message called `Parent Call` with tokens `child` and `room`. The real one is different, which is why this was checked: ``` name Parent Caller uuid 7D044452-B5A1-49F5-AC9C-1FD53A9A7353 index 2 text {Name}'s parent please go to the {Room} tokens Name, Room <- capitalised visible_on_network: true ``` Nothing was created or renamed. The coordinator is configured to match what is there. Because the template reads "...please go to the {Room}", the room token wants a human room name — "Nursery", not the `nursery` slug the topic uses. The coordinator maps slug to display name, configurably. ## The finding that shaped the design **An unknown token name is silently accepted.** ``` POST /v1/message/{uuid}/trigger [{"name":"child","text":{"text":"SHOULD NOT APPEAR"}}] -> HTTP 204 -> message goes on screen showing the PREVIOUS token values ``` Verified deliberately, with a known baseline set and cleared first, and a 2 second settle before reading state. Two things follow, and both are in the adapter: 1. **A 204 does not mean the right thing was displayed.** If the token names were misconfigured, every parent call would return 204 — so the teacher would be told "Sent to sanctuary" — while the sanctuary screen showed *the previous child's name and room*. In a church that is the worst failure this system could have: the wrong family walks out. So the coordinator reads the live message definition and refuses to trigger unless the configured token names actually exist in it. A mismatch is reported as an error and never as success. 2. **Token values persist between triggers.** Every trigger therefore sends both tokens, always, so a call can never inherit half of the one before it. ## Timing The API returns before its own state settles: reading `/v1/messages` immediately after a `204` can still show the previous values, and the new ones appear within about a second. Nothing in the coordinator reads back state to confirm a trigger, so this only matters to anyone debugging by hand — do not believe a read taken in the same second. `is_active` goes `true` on trigger and `false` on clear, and token values survive a clear.