CommandService and QueryService are the ConnectRPC API on -listen: one port, three wire formats, a write service and a read service kept strictly apart. This is the API the dashboard itself calls, so nothing reachable through it is a second-class integration.

1. One port, three protocols

jaque speaks ConnectRPC: plain JSON over HTTP/1.1 (curl-friendly, no generated client needed), gRPC, and gRPC-Web, all on the same port as the dashboard and /metrics (-listen).

curl -s -X POST http://127.0.0.1:8080/jaque.v1.QueryService/ListStatus \
  -H 'Content-Type: application/json' -d '{}'

2. CommandService -- writes

Six RPCs, one per command variant: ProcessCheckResult, ProcessCheckResults (batch, all-or-nothing validation, in-order enqueue), AcknowledgeProblem, RemoveAcknowledgement, ScheduleDowntime, DeleteDowntime. AcknowledgeProblem, RemoveAcknowledgement and ScheduleDowntime all take a Target, which is either one object (host/service) or every object a label selector matches -- the same mechanism the dashboard's bulk actions use.

A success response means enqueued, not applied -- the engine resolves commands asynchronously at its own pace.

-api-token (empty by default, meaning open) protects writes only:

curl -s -X POST http://127.0.0.1:8080/jaque.v1.CommandService/AcknowledgeProblem \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <token>' \
  -d '{"target":{"object":{"host":"gw"}},"sticky":true,"author":"ops","comment":"known issue"}'

3. QueryService -- reads, no token required

ListStatus (current state of one host, one service, or the whole fleet -- optionally narrowed by a label selector), ListHistory (recent transitions for one object or the global feed), ListObjects (every configured object plus its labels), ListContacts, ListViews, ListSinks (the configured perfdata sinks -- name, type, input and selector), and GetServerInfo (the running binary's version -- the release-stamped vX.Y.Z, or "dev" for anything else). Every read comes from the projection, never from the engine or the event log directly -- reads never block on write throughput. Unlike CommandService, reads never require -api-token: the bearer token protects writes only.

4. This is the dashboard's own API

Every action in Dashboard -- acknowledge, downtime, the status table, history -- is a call to one of these RPCs. There's no separate, richer internal API the UI gets and scripts don't.

5. Security considerations

-api-token, when set, is checked with a constant-time comparison so a response-time difference cannot leak how much of the token matched; when unset every CommandService write is open to anyone who can reach -listen. QueryService is never gated by -api-token, by design -- see section 3 -- so it should not carry anything an unauthenticated caller should not see: ListSinks and ListContacts deliberately omit sink URLs, headers and contact target payloads (webhook URLs, command lines) from their responses, because those can carry credentials. AcknowledgeProblem and ScheduleDowntime's author/comment fields are operator-supplied free text with no server-side validation beyond the RPC's type -- the same posture the event log carries them into, see Event log schema, section 4. There is no transport encryption at this layer: run behind a reverse proxy or a network boundary you control if -listen is reachable beyond a trusted network.