API
Everything the dashboard does goes through a REST API, which you can use for integrations.
- Base path:
/v1. Browsers use the dashboard's own/v1proxy; servers can call the API directly (port 8000). - Interactive docs:
GET /v1/docs(Swagger UI) andGET /v1/docs/openapi.json. - Health:
GET /v1/status→{status:"ok"};GET /v1/health;GET /ping→ status, node and build.
Authentication
curl -s https://orbit.example.org/v1/auth/login \
-H 'content-type: application/json' \
-d '{"email":"integration@acme.test","password":"…","tenantKey":"acme"}'
The response contains accessToken and refreshToken. Send Authorization: Bearer <accessToken> on every call, and refresh with the refresh token before the access token expires (30 minutes by default). Accounts with two-step verification get a challenge instead; use a dedicated integration account.
Requests run with the account's role, sites and licenses, exactly like the dashboard.
Conventions
| Topic | Convention |
|---|---|
| Bodies | JSON, camelCase |
| Single item | {"data": {...}} |
| Lists | {"items": [...], "page", "limit", "total", "totalPages"} |
| Errors | {"error": "Short Title", "message": "Detail"} with 400, 401, 403, 404, 405, 409, 413, 422, 429 or 503 |
| Paging | page (from 1), limit (1–200, default 25) |
| Request IDs | Send X-Request-ID or get one generated; it's echoed back and stored in the audit log |
Generic resources
Most tenant data follows one pattern:
GET|POST /v1/<resource>
GET|PATCH|DELETE /v1/<resource>/<id>
GET|POST|PUT /v1/<parent>/<parentId>/<child>
PATCH|DELETE /v1/<parent>/<parentId>/<child>/<childId>
- Filters: any query parameter named like a column filters by exact match; repeat it for IN. Many resources also accept
search. - Sorting:
orderBy=<column>&order=asc|desc. - Soft delete: deleted rows are hidden unless
includeDeleted=true. - Create: unknown fields are rejected with 400; IDs and timestamps are filled in by the server.
- Permissions: GET needs the resource's read permission, other methods its write permission, then the license check applies.
Examples: /v1/clients, /v1/cases, /v1/clients/<id>/notes, /v1/employers/<id>/contacts, /v1/job-postings/<id>/applications, /v1/definition-sets/<id>/definitions.
Useful dedicated endpoints
| Endpoint | Purpose |
|---|---|
GET /v1/auth/me |
Who am I, tenant, sites, permissions |
GET /v1/appointments/calendar?from&to |
Expanded occurrences |
POST /v1/appointments/conflicts |
Dry-run conflict check |
GET /v1/definition-lookup?sets=a,b |
Definition values by set code |
POST /v1/file (multipart) |
Upload a document; GET /v1/file/<id> downloads |
GET /v1/imports/supported-entities |
Import field registry |
POST /v1/imports/run |
Run an import now (documentId + templateId, or targetEntity + mapping) |
POST /v1/imports/upload (multipart) |
Queue an import for the worker |
GET/POST /v1/import-templates |
Templates |
POST /v1/forms/<id>/submissions |
Submit a form (answers keyed by field key) |
POST /v1/reports/<id>/run, /export |
Reports |
GET /v1/audit-logs |
Audit trail |
GET/PUT /v1/settings/<category> |
Settings (general, terminology, notifications, scheduler, classification, documents) |
/v1/<tenant>/public/… |
Unauthenticated portal endpoints (rate limited) |
See /v1/docs for everything else.
Example: queue an import from a script
curl -s https://orbit.example.org/v1/imports/upload \
-H "Authorization: Bearer $TOKEN" \
-F file=@clients.csv \
-F templateId=<template id>
# → a pending job; poll GET /v1/imports/<id> until completed, then GET /v1/imports/<id>/rows