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 (
…/exporton the AI API) and some ingest operations run for minutes; the gateway allows up to 10 minutes for them. POST /workflows/workflows/run/streamstreams 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.