--- type: api title: System Endpoints description: Bootstrap payload, public event status, public/authenticated SSE streams, and public event-window timestamps. tags: [api, system, bootstrap, event, sse, settings] timestamp: 2026-07-21T22:19:08Z --- # Endpoints | Method | Path | Auth | Source | |--------|-----------------------------------|--------|-----------------------------------------------------| | `GET` | `/api/v1/bootstrap` | Public | `backend/src/modules/system/system.controller.ts` | | `GET` | `/api/v1/event/status` | Public | Same. | | `GET` | `/api/v1/event/stream` | Public (SSE) | Same. | | `GET` | `/api/v1/settings/event` | Public | Same. | | `GET` | `/api/v1/events/status` | Authenticated (SSE) | Same. | | `GET` | `/api/v1/scoreboard/stream` | Public (SSE) | Same. | > Path note: the **authenticated** status stream is mounted at the plural > `/api/v1/events/status` so it can be distinguished from the legacy > public `/api/v1/event/status` snapshot endpoint. # `GET /api/v1/bootstrap` Built by `SystemService.bootstrap()`. Public payload consumed by the SPA's `BootstrapService`: ```json { "initialized": true, "pageTitle": "HIPCTF", "logo": "", "welcomeMarkdown": "# Welcome\n\n...", "theme": { "id": "classic", "tokens": { "...": "..." } }, "defaultChallengeIp": "127.0.0.1", "registrationsEnabled": false, "passwordPolicy": { "minLength": 12, "requireMixed": true, "description": "At least 12 characters with upper, lower, digit and symbol" } } ``` * `initialized` is `true` iff at least one admin user exists. * `theme` is the resolved `Theme` (one of the 10 canonical themes; see [Theming](/guides/theming.md)). * `registrationsEnabled` is read from the `setting` table (`SETTINGS_KEYS.REGISTRATIONS_ENABLED`) and gates the new public register endpoint (see [Auth Endpoints](/api/auth.md)). * `passwordPolicy` is derived from `PASSWORD_MIN_LENGTH` / `PASSWORD_REQUIRE_MIXED` env vars (see [Change Password Guide](/guides/change-password.md)). # `GET /api/v1/event/status` (legacy public snapshot) Returns the current event window computed by `EventStatusService.getStatus()`: ```json { "state": "Running", "countdownMs": 12345, "startUtc": "...", "endUtc": "...", "serverNowUtc": "..." } ``` `status` is `Stopped` while `now < eventStartUtc` (countdown), `Running` between start and end, and `Stopped` once `now >= eventEndUtc`. This endpoint is preserved for backward compatibility — new consumers should use `getState()` (see below). # `GET /api/v1/settings/event` (public timestamps) Returns the raw UTC event-window timestamps without computing state. Useful for the SPA when only the window endpoints are needed: ```json { "eventStartUtc": "2026-07-21T12:00:00.000Z", "eventEndUtc": "2026-07-28T12:00:00.000Z" } ``` A `null` value for either field means that the underlying `setting` row is missing or empty; in that case `EventStatusService.getState()` returns the `unconfigured` state. # `GET /api/v1/events/status` (authenticated SSE) Authenticated Server-Sent Events stream that pushes the full `EventStatePayload` whenever it changes. Protected by the global `JwtAuthGuard` — unauthenticated clients receive `401` before any frame is sent. Each frame: ```json { "state": "countdown" | "running" | "stopped" | "unconfigured", "serverNowUtc": "2026-07-21T12:00:00.000Z", "eventStartUtc": "2026-07-21T12:00:00.000Z" | null, "eventEndUtc": "2026-07-28T12:00:00.000Z" | null, "secondsToStart": 3600, "secondsToEnd": 604800 } ``` * `state` transitions: * `unconfigured` — `eventStartUtc`/`eventEndUtc` settings are missing or unparseable. * `countdown` — `now < eventStartUtc`. * `running` — `start <= now <= end`. * `stopped` — `now > eventEndUtc`. * The stream emits: 1. An **initial** frame on connect (`defer(getState())`). 2. A **60-second tick** frame so the SPA can update even if no admin cron publishes through the hub. 3. Any frame pushed via `SseHubService.publish()`. * Consecutive identical payloads are suppressed via `distinctUntilChanged(JSON.stringify)`. See `backend/src/common/services/event-status.service.ts` for the authoritative state machine; see [Event Window Guide](/guides/event-window.md) for the full diagram and the SPA wiring. # `GET /api/v1/event/stream` (public SSE, legacy) Public, flattened event stream that emits the legacy payload shape (`status`, `countdownMs`, `startUtc`, `endUtc`, `serverNowUtc`) on a 1-second tick and on hub pushes. Preserved for backward compatibility with the original landing page status badge. # `GET /api/v1/scoreboard/stream` Public SSE stream that pushes a flattened solve payload whenever a new solve is published (`backend/src/common/services/sse-hub.service.ts`). # See also - [Auth and Settings Tables](/database/auth-settings.md) - [Theming](/guides/theming.md) - [Event Window Guide](/guides/event-window.md) - [Scoreboard Stream Guide](/guides/scoreboard-stream.md) - [Authenticated Shell Guide](/guides/authenticated-shell.md)