Skip to main content

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

RolePurpose
Camera.OperateRequired for PTZ movement, focus, brightness, guard tour, lease management, and activity logs
Notification.AlertRequired for creating alert messages
Notification.SubscribeRequired for managing notification subscriptions
AI.AccessGrants access to AI-specific operational metadata fields

Base Controller Pattern

All controllers inherit from ApiControllerBase, which provides:

  • Entra ID claim extraction: EntraUserId (from oid claim), EntraDisplayName, EntraEmail, CompanyName
  • MediatR dispatch: The Mediator property sends commands and queries through the CQRS pipeline
  • Role checking: HasRole(string role) helper method

Authorization

Base path: /authorization
Auth: Anonymous

MethodRouteDescription
GET/authorization/loginRedirects 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

MethodRouteDescriptionAuth
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-staticGet 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-entraidGet 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

MethodRouteDescription
POST/cameramovement/ptzPan/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/homeMove camera to its home (default) position. Same validation flow as PTZ. Returns lease data.
POST/cameramovement/focusSet camera focus. Supports manual focus value and auto-focus toggle.
POST/cameramovement/brightnessAdjust camera brightness. Supports a specific value or resetDefault to restore default (5000).
POST/cameramovement/toggle-guardtourToggle guard tour (patrol) mode on/off. Validates that the device supports autopan. Broadcasts an activity log message after toggling.
POST/cameramovement/turboActivate turbo mode for a camera. Sends request to the Image Acquisition API.

Lease & Movement Management

MethodRouteDescription
PUT/cameramovement/close-lease/{id}Close an active camera lease. Sets end time and calculates actual duration.
PUT/cameramovement/movement-extendExtend the movement expiration for a camera. Minimum extension is 60 minutes from the current time.
PUT/cameramovement/movement-endEnd 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:

  1. User sends a movement request (PTZ, home, focus, brightness)
  2. API validates user has access to the camera and the camera is an active RealCam
  3. API sends an HTTP trigger to the Image Acquisition API (with x-api-key header)
  4. Image Acquisition processes the movement and calls back to POST /functionendpoints/leaseCameraAfterMove
  5. The callback creates a lease record (default 60 seconds) and patches the camera's operational state in Cosmos DB
  6. Activity log is broadcast via SignalR to connected clients

Images

Base path: /images
Auth: Anonymous

MethodRouteDescription
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

MethodRouteDescriptionAuth
POST/alerts/alert-createCreate a new alert message with an optional map image (PNG, multipart/form-data).Notification.Alert
POST/alerts/subscribeCreate a new subscription, or update an existing one if id is provided in the request body.Notification.Subscribe
GET/alerts/subscriptionGet the current user's subscriptions.Notification.Subscribe
GET/alerts/subscription-locationsGet available subscription locations.Notification.Subscribe
PUT/alerts/subscription-pausePause 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

MethodRouteDescription
POST/notifications/subscribeCreate a new notification subscription.
GET/notifications/subscriptionGet the current user's notification subscriptions.
GET/notifications/subscription-locationsGet available notification locations.
PUT/notifications/subscription-updateUpdate an existing subscription.
PUT/notifications/subscription-pausePause 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

MethodRouteDescription
POST/activitylog/add-messageAdd 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

MethodRouteDescription
GET/user/ui-settingsGet the authenticated user's UI settings from Cosmos DB.
PUT/user/activity-log-read-dateUpdate the user's last activity log read date.
PUT/user/pin-hide-camera-updateUpdate the user's pinned and hidden camera lists.
PUT/user/layer-visibility-updateUpdate the user's map layer visibility preferences.
PUT/user/camera-options-updateUpdate 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)

MethodRouteDescription
GET/featureflagsRetrieve 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

MethodRouteDescriptionAuth
GET/sharedviews/{sharedViewId}Get a shared view by its unique ID. Returns the saved view state.Anonymous
POST/sharedviewsCreate 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)

MethodRouteDescription
POST/functionendpoints/leaseCameraAfterMoveCallback 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.
caution

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.