API Endpoints
This page documents all REST endpoints exposed by the Frontend API. All endpoints are routed via ASP.NET Core attribute routing with the controller name as the base path (e.g., CamerasController → /cameras).
Authentication & Authorization
The API uses Microsoft Entra ID (Azure AD) with JWT Bearer tokens for authentication. Tokens are obtained via the /authorization/login flow and passed as Authorization: Bearer <token> headers.
Security Roles
| Role | Purpose |
|---|---|
Camera.Operate | Required for PTZ movement, focus, brightness, guard tour, lease management, and activity logs |
Notification.Alert | Required for creating alert messages |
Notification.Subscribe | Required for managing notification subscriptions |
AI.Access | Grants access to AI-specific operational metadata fields |
Base Controller Pattern
All controllers inherit from ApiControllerBase, which provides:
- Entra ID claim extraction:
EntraUserId(fromoidclaim),EntraDisplayName,EntraEmail,CompanyName - MediatR dispatch: The
Mediatorproperty sends commands and queries through the CQRS pipeline - Role checking:
HasRole(string role)helper method
Authorization
Base path: /authorization
Auth: Anonymous
| Method | Route | Description |
|---|---|---|
GET | /authorization/login | Redirects to Microsoft Entra ID login page. Returns an authorization URL for obtaining a JWT token. |
GET | /authorization/callback?code={code}&state={state} | OAuth2 callback endpoint. Exchanges the authorization code for access and refresh tokens. |
Usage: Navigate to /authorization/login in a browser. After authenticating, the callback returns token data that can be used with the Swagger Authorize dialog or as a Bearer token in API requests.
Cameras
Base path: /cameras
Auth: Most endpoints are anonymous; cameras-by-entraid requires Camera.Operate
| Method | Route | Description | Auth |
|---|---|---|---|
GET | /cameras/static?cameraIds={id1}&cameraIds={id2} | Get static metadata (name, location, model) for specified camera IDs. If the user is authenticated, results are filtered by user access. | Anonymous |
GET | /cameras/all-static | Get static metadata for all cameras. If authenticated, filtered by user access permissions. | Anonymous |
GET | /cameras/operational?since={date}&cameraIds={ids}&getImages={bool}&getPatrolMode={bool} | Get operational metadata (pan, tilt, zoom, status). Supports optional time filter, camera filter, and flags for image/patrol data. Users with AI.Access role see additional fields. | Anonymous |
GET | /cameras/cameras-by-entraid | Get the list of cameras the authenticated user has access to, based on their Entra ID. | Camera.Operate |
GET | /cameras/state?deviceId={id} | Get current device state for a camera. | Anonymous |
Camera Movement
Base path: /cameramovement
Auth: All endpoints require Camera.Operate role
Movement Operations
| Method | Route | Description |
|---|---|---|
POST | /cameramovement/ptz | Pan/Tilt/Zoom camera. Validates camera access for the authenticated user, checks the device is an active RealCam, then queues a movement trigger to the Image Acquisition API. Returns lease data on callback. |
POST | /cameramovement/home | Move camera to its home (default) position. Same validation flow as PTZ. Returns lease data. |
POST | /cameramovement/focus | Set camera focus. Supports manual focus value and auto-focus toggle. |
POST | /cameramovement/brightness | Adjust camera brightness. Supports a specific value or resetDefault to restore default (5000). |
POST | /cameramovement/toggle-guardtour | Toggle guard tour (patrol) mode on/off. Validates that the device supports autopan. Broadcasts an activity log message after toggling. |
POST | /cameramovement/turbo | Activate turbo mode for a camera. Sends request to the Image Acquisition API. |
Lease & Movement Management
| Method | Route | Description |
|---|---|---|
PUT | /cameramovement/close-lease/{id} | Close an active camera lease. Sets end time and calculates actual duration. |
PUT | /cameramovement/movement-extend | Extend the movement expiration for a camera. Minimum extension is 60 minutes from the current time. |
PUT | /cameramovement/movement-end | End movement expiration for a camera immediately. |
GET | /cameramovement/lease/{cameraId} | Get the latest active lease and movement reason for a camera, if one exists. |
GET | /cameramovement/latest-move-by-camera/{cameraId} | Get the latest camera movement record including the user who performed it. |
Camera Movement Flow:
- User sends a movement request (PTZ, home, focus, brightness)
- API validates user has access to the camera and the camera is an active
RealCam - API sends an HTTP trigger to the Image Acquisition API (with
x-api-keyheader) - Image Acquisition processes the movement and calls back to
POST /functionendpoints/leaseCameraAfterMove - The callback creates a lease record (default 60 seconds) and patches the camera's operational state in Cosmos DB
- Activity log is broadcast via SignalR to connected clients
Images
Base path: /images
Auth: Anonymous
| Method | Route | Description |
|---|---|---|
GET | /images/latest-by-cameras?cameraIds={id1}&cameraIds={id2} | Get the latest image metadata for multiple cameras at once. |
GET | /images/latest-by-camera/{cameraId} | Get the latest image metadata for a single camera. |
GET | /images/timelapse-by-camera/{cameraId}?startTime={start}&endTime={end} | Get image metadata for a camera over a time range. Maximum range is 6 hours. |
GET | /images/panorama-timelapse-by-camera/{cameraId}?startTime={start}&endTime={end} | Get panorama image metadata for a camera over a time range. Maximum range is 6 hours. |
GET | /images/latest-panorama-for-camera/{cameraId} | Get the latest panorama image metadata for a camera. |
GET | /images/generate-gif-by-period-for-camera/{cameraId}?startTime={start}&endTime={end} | Generate and return an animated GIF from single images over a time range. Max range is 6 hours. Returns image/gif content. |
GET | /images/generate-gif-by-period-for-Pano/{cameraId}?startTime={start}&endTime={end} | Generate and return an animated GIF from panorama images over a time range. Max range is 60 minutes. Returns image/gif content. |
Image Metadata Fields: CameraId, Timestamp, ImageUrl, ThumbnailImageUrl, Pan, Tilt, Zoom, Focus, LatencyInSeconds
Panorama Metadata Fields: CameraId, Timestamp, ImageUrl, IsClearDay
Alerts
Base path: /alerts
Auth: Requires authentication; specific roles per endpoint
| Method | Route | Description | Auth |
|---|---|---|---|
POST | /alerts/alert-create | Create a new alert message with an optional map image (PNG, multipart/form-data). | Notification.Alert |
POST | /alerts/subscribe | Create a new subscription, or update an existing one if id is provided in the request body. | Notification.Subscribe |
GET | /alerts/subscription | Get the current user's subscriptions. | Notification.Subscribe |
GET | /alerts/subscription-locations | Get available subscription locations. | Notification.Subscribe |
PUT | /alerts/subscription-pause | Pause an active subscription. | Notification.Subscribe |
PUT | /alerts/subscription-delete/{id} | Soft-delete a subscription by ID. | Notification.Subscribe |
Notifications
Base path: /notifications
Auth: All endpoints require Notification.Subscribe role
| Method | Route | Description |
|---|---|---|
POST | /notifications/subscribe | Create a new notification subscription. |
GET | /notifications/subscription | Get the current user's notification subscriptions. |
GET | /notifications/subscription-locations | Get available notification locations. |
PUT | /notifications/subscription-update | Update an existing subscription. |
PUT | /notifications/subscription-pause | Pause a subscription. |
PUT | /notifications/subscription-delete/{id} | Soft-delete a subscription. |
Subscription Model: Supports ESRI-based geographical subscriptions (with buffer zones), point-based anomaly alerts, configurable urgency levels, communication types, and day/time range filters.
Activity Log
Base path: /activitylog
Auth: All endpoints require Camera.Operate role
| Method | Route | Description |
|---|---|---|
POST | /activitylog/add-message | Add an activity log message for a camera. After insertion, the latest message is fetched and broadcast to the camera's SignalR group. |
GET | /activitylog/{cameraId}?count={n} | Get the latest activity log messages for a camera. Optional count parameter limits results. |
AddMessageRequest Fields: CameraName, Message, IsHighPriority, IsSystem
The user's EntraUserId, EntraDisplayName, and CompanyName are automatically populated from JWT claims.
User
Base path: /user
Auth: Requires authentication
| Method | Route | Description |
|---|---|---|
GET | /user/ui-settings | Get the authenticated user's UI settings from Cosmos DB. |
PUT | /user/activity-log-read-date | Update the user's last activity log read date. |
PUT | /user/pin-hide-camera-update | Update the user's pinned and hidden camera lists. |
PUT | /user/layer-visibility-update | Update the user's map layer visibility preferences. |
PUT | /user/camera-options-update | Update the user's camera display options. |
All user preference data is stored in Cosmos DB, keyed by the user's Entra ID.
Feature Flags
Base path: /featureflags
Auth: None (open endpoint)
| Method | Route | Description |
|---|---|---|
GET | /featureflags | Retrieve all feature flags from Azure App Configuration. |
Feature flags allow the frontend to enable/disable functionality dynamically without code changes.
Shared Views
Base path: /sharedviews
Auth: GET is anonymous; POST requires authentication
| Method | Route | Description | Auth |
|---|---|---|---|
GET | /sharedviews/{sharedViewId} | Get a shared view by its unique ID. Returns the saved view state. | Anonymous |
POST | /sharedviews | Create a new shared view. Returns the generated shared view ID. | Authenticated |
Shared views allow users to save and share camera view configurations via a URL.
Function Endpoints (Internal)
Base path: /functionendpoints
Auth: Anonymous (called by Image Acquisition orchestration)
| Method | Route | Description |
|---|---|---|
POST | /functionendpoints/leaseCameraAfterMove | Callback endpoint invoked by the Image Acquisition API after a camera movement completes. Creates a camera lease, patches operational state in Cosmos DB, and broadcasts an activity log message via SignalR. |
This endpoint is intended for internal service-to-service communication only. It is called by the Image Acquisition Azure Functions after processing a camera movement trigger.