EARLY ACCESS Muster is being validated by pilot departments. Schedule a walk-through →

API changelog

Every schema-version bump. Additive changes are noted so integrators can enable new features without a breaking-change migration; removals happen only in a new v2 proto package with the standard 12-month deprecation window per docs/ROADMAP.md Phase 7 §"API discipline requirements."


1.3 — GetIncidentUnitMovement Layer 1 read method (2026-07-07)

What's new:

  • GET /v1/departments/{deptId}/incidents/{incidentId}/unit-movement — per-unit GPS movement trace summary for an incident. Response envelope: {"incident_id": "...", "unit_movement": [{...}]}. Each row: unit_id, designation, fix_count, first_fix_at, last_fix_at, approximate_distance_meters (haversine sum), average_accuracy_meters, bounding box (min_latitude / max_latitude / min_longitude / max_longitude), and optional max_speed_mps (omitted when no fix reported speed). Same 404 semantics as GetIncident (null → not found); empty unit_movement list when the log is non-empty but recorded no UnitLocationReported events.

    Wraps the pure summarizeUnitMovement projection from core_domain — same aggregation the after-action PDF's Section 9b renders. Gives integrators programmatic access without parsing the PDF.

  • New capability incident.unit_movement (sinceVersion: "1.3") exposed via GetEffectiveCapabilities.

  • GET /v1/departments/{deptId}/incidents/{incidentId} response envelope gains an optional movement_summary field — same row shape as the dedicated /unit-movement endpoint. Present when the incident recorded ≥1 GPS fix; omitted when empty. Additive convenience so integrators polling GetIncident don't need to chain a second call. Pre-1.3 clients ignore the missing / new key cleanly (no wire-format break).

What's deprecated: None.

Wire-format breaks: None. Every change is additive.


1.2 — Integration registry LIST + DELETE + per-department authorization gate (2026-07-07)

What's new:

  • GET /v1/integrations — enumerate every registered integration. Response envelope: {"integrations": [...]}. Open to every api_read_v1 caller (integration metadata is not sensitive; enumeration is expected for the admin console + integrator directory pages). Wired in IntegrationRegistryFirestoreService.list().

  • DELETE /v1/integrations/{integration_id} — unregister an integration. Ownership check: JWT's sub must match the doc's registrant_sub. 403 on mismatch, 404 on missing. Response: {"deleted": true}. Wired in IntegrationRegistryFirestoreService.delete().

    Downstream effect. After delete, the producer-capability gate rejects every ingest row for the integration's api_keys because the registry lookup returns null (fail-closed). Active Layer 3 WebSocket subscriptions on the integration's JWT continue until the JWT expires.

  • Per-department integration authorization gate. Every request whose URL targets a department other than the JWT's scope now consults departments/{deptId}/authorized_integrations/{integrationId}. Missing → 403 with actionable message pointing at the admin console. Revoked → 403 with the revocation timestamp. Active → allowed. Customer-scoped JWTs (JWT dept matches URL) skip the gate entirely. 1-minute TTL cache. See the Authentication guide §"Two-step onboarding" for the full model.

What's deprecated: None.

Wire-format breaks: None. Every change is additive.


1.1 — Layer 3 Firestore-backed live event stream (2026-07-06)

What's new:

  • Live event tail on the wss://…/subscribe transport now actually pushes new events, not just replays history and hangs idle. Implementation: a Firestore-poll adapter (FirestoreIncidentEventStream) polls the same collection the read path queries on a 2-second interval with a per-watch cursor. Latency: two-to-three seconds worst case. Multi-subscriber fan-out shares one upstream poll per (department, incident); broadcast controller emits to all attached subscribers.

What's deprecated: None.

Wire-format breaks: None. Additive substrate change; the subscribe transport's wire format is unchanged.


1.0 — Layer 1 read + Layer 2 write + Layer 3 subscribe (2026-07-06)

Inaugural release. All three layers now shipped:

  • Layer 1 read — 8 methods across IncidentReadService, TrustKeysService.
  • Layer 2 write ingestPOST /v1/departments/{deptId}/events with producer-capability enforcement.
  • Layer 3 subscribewss://…/subscribe WebSocket transport with history-replay + snapshot-end boundary + live tail.

Dart SDK published as muster_api_client on pub.dev. Python + TypeScript + Go + Java SDKs generated from the same proto files; publishing is manual per language on customer demand (see PUBLIC_API_CLIENT_SDKS.md).


Format for future entries

## <schema-version> — <feature> (<date>)
              
              **What's new:**
              - (list of additive changes; every change references the
                proto file + method or field)
              
              **What's deprecated:**
              - (endpoints or fields marked deprecated; Sunset date; 12-month
                removal window applies)
              
              **Wire-format breaks:** None. (Wire breaks require v2.)