API Overview
The Eviworx REST API enables programmatic access to all platform features. The API is fully RESTful, uses JSON for request/response bodies and is served via Traefik as API gateway.
Base URL
https://your-eviworx-instance.com/api
All API requests go through Traefik (port 443), which forwards them to the backend (port 3000).
Authentication
Every request is attributed either to a user or to an API key. Both are subject to the same role-based permissions:
| Actor | Mechanism | Usage |
|---|---|---|
| User | JWT as HttpOnly cookie (session) | Frontend/portal; token NOT in body, MFA/TOTP optional |
| API-Key | X-API-Key Header | External integrations. A key without a role has no permissions. The key is only accepted in the X-API-Key header, not as Authorization: Bearer. |
Most endpoints accept both. Some are restricted to logged-in users and answer an API key with 403, e.g. reports, forms, linking lists and response templates. Permissions are resolved per role; changes to a role take effect immediately. Details: Authentication · RBAC.
Enum Convention (important)
Enum values are written in uppercase in both requests and responses. Lowercase values are rejected with 400. Example ticket priority: "HIGH".
// POST /api/tickets
{ "priority": "HIGH" }
// Response:
{ "priority": "HIGH", "status": "OPEN" }
// "priority": "high" → 400
Applies analogously to visibility/status (knowledge base), category enums (forms), impact/urgency (incidents), changeType (changes) etc. Free-form fields (e.g. tags) are unaffected. Valid values are listed on the domain pages, as are the few lowercase value sets such as the CronJob action types.
Available Endpoints
ITSM Core
| Module | Endpoint | Description |
|---|---|---|
| Tickets | /api/tickets |
CRUD, categories, participants (follower/CC), email actions |
| Incidents | /api/incidents |
CRUD, GDPR flow, evidence checklists, categories |
| Problems | /api/problems |
CRUD, categories, root cause analysis |
| Changes | /api/changes |
CRUD, approvals, templates, categories, BACKED_OUT status |
| Approvals | /api/approvals |
Unified Approvals API (changes, incidents etc.) |
| Linking | /api/linking |
Entity linking (ticket↔problem, asset↔contract etc.) |
Asset Management
| Module | Endpoint | Description |
|---|---|---|
| Assets | /api/assets |
CRUD, checkout/checkin, QR scan |
| Asset Types | /api/asset-types |
AssetType management incl. policies |
| Asset Categories | /api/asset-categories |
Category management |
| Asset Locations | /api/asset-locations |
Location management |
| Asset Relations | /api/asset-relations |
CMDB relations between assets |
| Model Clusters | /api/asset-model-clusters |
Model deduplication & clustering |
| Handover | /api/handovers |
QR/PDF-based asset handover |
| Inventory | /api/inventory-sessions |
Inventory sessions with workflow integration |
Automation & Workflows
| Module | Endpoint | Description |
|---|---|---|
| Workflows | /api/workflow |
Templates, instances, tasks, publishing, versioning |
| CronJobs | /api/cronjobs |
Scheduled jobs, config, executions, 28 action types |
| SLA | /api/sla |
SLA policies, business hours, holidays, escalation |
Users & Security
| Module | Endpoint | Description |
|---|---|---|
| Auth | /api/auth |
Login, logout, refresh, 2FA/TOTP, forgot/reset password |
| Users | /api/users |
User management, invitation email, notification preferences |
| Roles | /api/roles |
Role management with permissions |
| Agents | /api/agents |
Agent profiles, groups, specialties, capacity |
| Absences | /api/absences |
Absence management (substitute, availability filter on assignment) |
| Entra ID | /api/entra-id |
SSO, OAuth callback, sync, config |
| API Keys | /api/api-keys |
API key management for external integrations |
| Audit | /api/audit |
Audit logs, enterprise audit, chain verification |
Communication & Email
| Module | Endpoint | Description |
|---|---|---|
| Notifications | /api/web-notifications |
In-app notifications, web push |
| Notification Templates | /api/notification-templates/v2 |
Multilingual notification templates |
| Mailboxes | /api/inbound-mailboxes |
Individual mailbox configuration (IMAP/Graph API) |
| Email Signatures | /api/email-signatures |
Email signatures per mailbox |
| Response Templates | /api/response-templates |
Canned responses for the ticket composer (scope PERSONAL/AGENT_GROUP/ORGANIZATION) |
| Teams Bot | /api/teams/bot |
Microsoft Teams Bot Framework endpoint |
Knowledge Management & Documents
| Module | Endpoint | Description |
|---|---|---|
| Knowledge Base | /api/knowledge-base |
Knowledge base articles |
| eLibrary | /api/elibrary |
Document library |
| Attachments | /api/attachments |
File attachments for all object types, virus scan status |
| Contracts | /api/contracts |
Contract management, asset linking |
| Licenses | /api/licenses |
License management, seat management, publisher/products |
Dashboards & Reports
| Module | Endpoint | Description |
|---|---|---|
| Dashboard | /api/dashboard |
Unified Workplace, NOC dashboard, widgets |
| Analytics | /api/analytics |
Interactive analytics reports |
| Reports | /api/reports |
Standard reports |
| Custom Reports | /api/custom-reports |
Custom reports, CSV/PDF export |
System & Configuration
| Module | Endpoint | Description |
|---|---|---|
| Settings | /api/settings |
System settings, email, Teams, notifications, system status |
| File Settings | /api/settings/file-settings |
File upload configuration |
| Search | /api/search |
Global search across nine entity types — own page |
| Saved Views | /api/saved-views |
Saved list layouts for eleven entities — own page |
| Forms | /api/forms |
Dynamic forms (role-based) |
| Health | /api/health |
Basic check and probes (live, ready) plus the system status of all services |
| Telemetry | /api/telemetry/client-error-batch |
Error reports from the browser (POST, auth optional, rate-limited) |
My-Tasks (Cross-Domain Aggregator)
/api/my-tasks returns the open work items of the logged-in user from all areas in one list. Included types (MyTaskType): TICKET, INCIDENT, PROBLEM, CHANGE, CHANGE_TASK, WORKFLOW_STEP. Approvals are served by /api/approvals.
| Method | Endpoint | Description |
|---|---|---|
GET | /api/my-tasks?scope=…&types=…&search=…&limit=…&offset=… | Work items of one scope (default own), response { data, pagination }. types = comma list, search = title/number (max 200 characters), limit 1–200 (default 50), offset from 0. Invalid values are rejected with 400. Counters are provided by /api/my-tasks/count. |
GET | /api/my-tasks/count?tz=… | Counters for ALL three scopes in one response: { total, byType, own, group, substitute }, each with total, byType, overdue and dueToday. The only parameter is tz (IANA zone for the day boundary of dueToday; without it the system zone applies). |
| scope | Set |
|---|---|
own | assigned to me (default) |
group | items of my groups WITHOUT an assignee — the pool I can pull from |
substitute | items of an agent I am currently substituting for |
The three sets are DISJOINT: an item lies in exactly one scope. A group item a colleague is already working on is therefore neither "my task" nor pool. Tickets, incidents and problems carry their dueDate from SLA tracking (response deadline before resolution deadline); a paused tracking carries slaState: PAUSED, no dueDate, and never counts as overdue.
The dashboard (unified workplace) uses this endpoint; the workflows and approvals pages refer to it (e.g. WORKFLOW_STEP tasks).
Getting Started
1. Login (Token as HttpOnly Cookie)
curl -X POST https://your-instance.com/api/auth/login \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{
"email": "admin@company.com",
"password": "your-password"
}'
Response (token is set as HttpOnly cookie, NOT in body):
{
"user": {
"id": "admin-user-001",
"email": "admin@company.com",
"name": "Admin User"
},
"expiresAt": "2026-03-17T13:00:00.000Z"
}
When MFA/TOTP is enabled, a 2FA challenge is returned instead:
{
"requiresTwoFactor": true,
"twoFactorEnabled": true,
"twoFactorPendingToken": "pending-token...",
"expiresAt": "2026-03-17T12:05:00.000Z",
"user": { "id": "...", "email": "admin@company.com" }
}
2. API Request (Cookie is sent automatically)
# With curl and a saved cookie:
curl -X GET https://your-instance.com/api/tickets \
-b cookies.txt \
-H "Content-Type: application/json"
# Or with an API key (for external integrations):
curl -X GET https://your-instance.com/api/tickets \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json"
HTTP Status Codes
| Code | Meaning |
|---|---|
200 | Success |
201 | Created |
400 | Bad Request — invalid input (errorCode VALIDATION_ERROR) |
401 | Unauthorized |
403 | Forbidden (missing permission, errorCode FORBIDDEN; required names the permission needed, see Error Handling) |
404 | Not Found (object not found, errorCode NOT_FOUND) |
409 | Conflict (concurrent modification or duplicate, errorCode DUPLICATE_ENTRY) |
429 | Too Many Requests (Rate Limit) |
500 | Internal Server Error (generic error message only) |
Error Handling
Errors are returned in the following format:
{
"error": "Validation failed",
"errorCode": "VALIDATION_ERROR",
"details": []
}
Fields: error (message), errorCode (code, e.g. VALIDATION_ERROR / DUPLICATE_ENTRY / NOT_FOUND / FORBIDDEN), optional details. 500 responses contain only a generic error message.
403 for a missing permission
Every rejection by the permission check carries errorCode FORBIDDEN and names the permission needed in the field required. For a plain permission, required is a string:
{
"error": "Insufficient permissions",
"errorCode": "FORBIDDEN",
"required": "tickets.viewAll",
"source": "redis"
}
For critical actions, required is an array; missing names the permission that is lacking:
{
"error": "Insufficient permissions",
"errorCode": "FORBIDDEN",
"required": ["tickets.delete"],
"missing": ["tickets.delete"],
"source": "database"
}
If any one of several permissions grants access to a route, required lists all of them:
{
"error": "Insufficient permissions",
"errorCode": "FORBIDDEN",
"required": ["tickets.viewAll", "tickets.viewOwn"],
"source": "redis"
}
Clients should therefore accept required as either a string or an array. source is for diagnostics only and shows where the checked permissions came from (redis = role cache, database = freshly loaded from the database). If the caller has no active role, the response is error "No active role assigned" with errorCode FORBIDDEN and detail "Please contact administrator", without required. Domain-specific rejections carry their own 403 codes (e.g. ABSENCE_VIEW_FORBIDDEN); they are listed on the respective API page.
Rate Limiting
Rate limiting is implemented at two levels:
| Level | Limit | Details |
|---|---|---|
| Traefik (Gateway) | 100 req/s, Burst 200 | Global for all API requests |
| Backend (Auth) | Restricted | Login, refresh, 2FA, password reset |
| Backend (File Upload) | 200/hour/IP | File uploads |
| Backend (E-Mail) | 60/min | Email sending |
| Backend (Critical Ops) | Restricted | Admin operations, CronJob execution |
Pagination
Most list endpoints share the same query parameters: page and per (page size with a per-endpoint maximum, e.g. tickets max 200/default 50, KB max 100/default 20) plus optional cursor. Filtering, search and sorting follow the FilterSpec of each entity.
# page-based:
GET /api/tickets?page=1&per=50
# cursor-based (large/live lists):
GET /api/tickets?cursor=clx-next&per=50
There are two response shapes (depending on endpoint):
// cursor-based (e.g. tickets):
{ "data": [ /* ... */ ], "cursor": "clx-next", "hasMore": true, "pagination": { "total": 420, "limit": 50 } }
// page-based (e.g. knowledge base):
{ "data": [ /* ... */ ], "pagination": { "page": 1, "limit": 20, "total": 42, "totalPages": 3, "hasMore": true } }
JWT-based authentication, 2FA/TOTP, session management
Create your first ticket via API