API overview
이 콘텐츠는 아직 번역되지 않았습니다.
The appliance exposes a REST API under /api/v1 and a WebSocket stream at
/ws/v1/stream, both on port 5080. The operator console uses the same
interfaces.
The full REST contract, with every request and response body, is the OpenAPI
file /openapi/rest-v1.json. It is generated from the
code and checked against real responses.
Public surfaces
Section titled “Public surfaces”| Surface | Use |
|---|---|
/api/v1/* | REST routes, authenticated per route |
/ws/v1/stream | Live detections, camera status and alarm events as JSON |
/whep/* | WebRTC video signalling. The video itself travels from the relay to the browser, not through the API |
GET /health/live | Anonymous liveness check. It answers 200 when the service is up |
Rules every route follows
Section titled “Rules every route follows”| Topic | Rule |
|---|---|
| Authentication | Send Authorization: Bearer <access token>. An access token is valid for 15 minutes. The refresh token is an HttpOnly cookie, ev_refresh, valid for 14 days. |
| Roles | read (Administrator, Engineer, Operator), configure-inference (Administrator, Engineer) and administer (Administrator). |
| Unclaimed device | Until an administrator is claimed, every path answers 403 NOT_PROVISIONED except /health/live, /api/v1/setup/* and /api/v1/system/info. |
| Errors | application/problem+json with a stable code. Branch on code, never on title or detail, which are prose and can be reworded. Field validation is 422 VALIDATION_FAILED with an errors map keyed by the JSON field name. |
| Concurrent edits | Reads of editable rows carry a weak ETag. Send it back as If-Match on a write. A missing If-Match gets 428, and a stale one gets 412 with the current version in current. |
| Partial updates | In a PATCH, a missing field means leave it unchanged, and an explicit null means clear it. |
| Lists | Always an object with an items array. Offset paging returns total, page and pageSize. Keyset paging returns total and nextCursor. |
| Asynchronous work | 202 Accepted means the work was requested, not finished. Read the outcome from a status route. |
| Audit | Every change that reaches its handler writes an audit entry named resource.action, for example camera.update. |
Live stream
Section titled “Live stream”- Request a ticket with
POST /api/v1/ws-ticketsand a bearer token. The reply is{ ticket, expiresInSeconds }. A ticket works once and lasts 30 seconds. - Open
GET /ws/v1/stream?ticket=<ticket>as a WebSocket. A missing, expired or used ticket answers401before the handshake. - The first frame is
hello. The socket starts with no cameras, so send{ "type": "subscribe", "cameras": ["<camera id>"] }for up to 64 cameras.
A detection arrives as a JSON object with no type field. Every other frame
has a string type: hello, subscribed, clock, cameraStatus, event and
alertState. Clients tell the two apart by whether type is present.
Up to 16 viewers can be connected at once by default. When the limit is reached
the server closes the socket with 1008 too many clients. A client that does not
read fast enough is closed with 1008 too slow, and should reconnect.
Versioning
Section titled “Versioning”The version is in the path, /api/v1 and /ws/v1. Within a version, new routes,
new optional request fields, new response fields and new error codes can be
added. Ignore fields you do not know, and handle an unknown error code by its
HTTP status class. Removing or renaming a route or field, changing a type or
meaning, or making a policy stricter is a breaking change. It goes through a
deprecation period or a new version path.
The REST API, the live stream and the detection payload are versioned
separately. The detection payload carries schemaVersion, currently "1.0".