The machine API product clients ship against
Externally consumed contracts: experiment assignment, the onboarding bundle and events endpoints, the two analytics collectors, the public blog read API, and the health probe. Everything else under /api is dashboard-internal.
Experiment assignment#
A product client with only a subject identifier gets a sticky variant and its public config. The same subject gets the same variant, and an exposure is committed in the same transaction. A journey whose contract sets kill_switch returns the empty assignment rather than a wrong one.
GET /api/experiments/assign?app_id=…&platform=…&surface=…&subject=…
{ "variant": "…", "config": { … }, "experimentId": "…" }Analytics collectors#
Browsers and mobile apps report user-visible actions and failures to POST /api/analytics/web/collect and POST /api/analytics/mobile/collect. Events land de-duplicated by event id, with attribution recorded once. Only allow-listed site ids are accepted, and oversized bodies are refused with 413. Reporting never throws in the client — a lost telemetry row never turns a handled failure into an unhandled one.
Public blog read#
The only unauthenticated read API serves published blog content per surface, consumed by the landing application.
GET /api/public/blog/[surface]
GET /api/public/blog/[surface]/[slug]Liveness#
curl -s https://<deployment>/api/health
{"status":"ok"}