Conventions

URLs

Every API lives under its own prefix, and everything after the prefix is the API's own path, unchanged:

https://api2.evercam.io/<api>/<the API's path>
API Example
Dash https://api2.evercam.io/dash/v2/cameras
Admin https://api2.evercam.io/admin/v2/admin/users
AI https://api2.evercam.io/ai/v2/projects/{project_exid}/gate-report/events
Labs https://api2.evercam.io/labs/copilot/conversations
Workflows https://api2.evercam.io/workflows/workflows/runs
360 / BIM / Drone https://api2.evercam.io/360/floors/, https://api2.evercam.io/bim/uploads/, https://api2.evercam.io/drone/uploads/

So an API's existing documentation applies as-is: take its path and prefix it with https://api2.evercam.io/<api>. Each API's reference under /docs already shows the full gateway URLs.

The list of APIs, with their specs, is machine-readable at /apis.json. Each OpenAPI document is at /openapi/<api>.json (or .yaml), ready for code generators.

Pagination

Each API keeps its own pagination style:

API Request Response
Dash, AI page, limit items, total, page, limit, from, to
360, BIM, Drone page, limit page, limit, total
Labs page, size total, from, to
Workflows limit, cursor nextCursor

Redirects

Some endpoints answer 302/307 to a pre-signed storage URL (clips, snapshots, exports, archives). Follow redirects; the target URL needs no Evercam credentials, and it expires after a while.

Long-running and streamed responses

  • Exports (…/export on the AI API) and some ingest operations run for minutes; the gateway allows up to 10 minutes for them.
  • POST /workflows/workflows/run/stream streams progress as newline-delimited JSON (application/x-ndjson). Read the body incrementally.
  • Snapshots and images are returned as binary bodies.

Uploads

360 walks, drone flights and BIM models are large. Upload the files to the tus upload server first, then send their URLs to the ingest API. Request bodies sent through the gateway are limited to 10–50 MB depending on the API.

Real-time (WebSockets)

Two APIs push events over WebSockets, proxied by the gateway. Both authenticate inside the connection (not with the Authorization header), and the API checks the credential:

Dash uses Phoenix channels. Get a short-lived socket token, then connect:

// POST https://api2.evercam.io/dash/v2/sockets/auth with your access token → { ws_token }
import { Socket } from "phoenix"
const socket = new Socket("wss://api2.evercam.io/dash/socket", { params: { ws_token: wsToken } })
socket.connect()
socket.channel(`users:${email}`).join()

Labs Copilot uses Socket.IO. Set the path to the gateway prefix:

import { io } from "socket.io-client"
const socket = io("https://api2.evercam.io", {
  path: "/labs/ws/copilot",
  auth: { token: accessToken },
  query: { userEmail: email },
})

Connections idle for 15 minutes (no messages either way; heartbeats count) are closed with code 1001. During gateway deploys, connections are closed with 1012 (service restart); reconnect. Both client libraries above do this by default. A refused handshake gets an HTTP problem response: 404 for paths without a WebSocket endpoint, 429 for more than 30 new connections a minute from one IP, 502 if the API is unreachable.

Browsers (CORS)

Every API can be called from a browser on any origin. Credentials go in the Authorization header; cookies aren't used. These response headers are readable from JavaScript: X-Request-Id, RateLimit-*, Retry-After, Location, Content-Disposition, WWW-Authenticate.

Versions

Paths keep each API's own versioning (/v2/… on Dash and AI). Deprecated endpoints announce it with Deprecation, Sunset and Link headers.