3312 lines
140 KiB
Markdown
3312 lines
140 KiB
Markdown
# ShopDB Flask - API Reference
|
|
|
|
Auto-inventoried across core + plugins (362 endpoints). Auth legend: none = public, jwt = login required, jwt-optional = works either way, admin = admin role, permission:x = named RBAC permission, api-key = X-API-Key managed token.
|
|
|
|
## core-identity
|
|
|
|
### POST /api/auth/login
|
|
**Auth:** none
|
|
**Params:** body: `username`, `password` (both required)
|
|
**Purpose:** Authenticate and issue JWT access+refresh tokens; per-IP fixed-window rate limit (429) and 5-strike/15-min account lockout.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/auth/login -H 'Content-Type: application/json' -d '{"username":"admin","password":"secret123"}'
|
|
```
|
|
|
|
### POST /api/auth/refresh
|
|
**Auth:** JWT (refresh token)
|
|
**Params:** none; refresh token in Authorization header
|
|
**Purpose:** Exchange a refresh token for a new access token (rejects inactive/deleted users).
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/auth/refresh -H "Authorization: Bearer $REFRESH_TOKEN"
|
|
```
|
|
|
|
### GET /api/auth/me
|
|
**Auth:** JWT
|
|
**Params:** none
|
|
**Purpose:** Return the authenticated user's profile, roles, permissions, `mustchangepassword` flag.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/auth/me -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### POST /api/auth/change-password
|
|
**Auth:** JWT
|
|
**Params:** body: `new_password` (min 8, required), `current_password` (required unless `mustchangepassword` is set)
|
|
**Purpose:** Self-service password change; forced first-login change skips `current_password`; clears lockout state.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/auth/change-password -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"current_password":"old","new_password":"newpass123"}'
|
|
```
|
|
|
|
### POST /api/auth/logout
|
|
**Auth:** JWT
|
|
**Params:** none
|
|
**Purpose:** Logout stub for frontend token cleanup (no server-side blacklist yet).
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/auth/logout -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/users
|
|
**Auth:** JWT + role `admin`
|
|
**Params:** none
|
|
**Purpose:** List all users ordered by username.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/users -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/users/<userid>
|
|
**Auth:** JWT (admin or self, checked inline)
|
|
**Params:** path: `userid` (int)
|
|
**Purpose:** Get one user; non-admins may only fetch their own record (403 otherwise).
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/users/7 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### POST /api/users
|
|
**Auth:** JWT + role `admin`
|
|
**Params:** body: `username`, `email`, `password` (required); `firstname`, `lastname`, `isactive`, `roles` [roleids], `mustchangepassword` (default true), `sendwelcome` (default true)
|
|
**Purpose:** Create a user, assign roles, audit-log, and best-effort send a welcome email with the temp password.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/users -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"username":"jdoe","email":"jdoe@example.com","password":"Temp1234","roles":[2]}'
|
|
```
|
|
|
|
### PUT /api/users/<userid>
|
|
**Auth:** JWT (admin or self; `isactive`/`roles`/`unlock` fields admin-only)
|
|
**Params:** path: `userid`; body: `email`, `firstname`, `lastname`, `password`; admin-only: `isactive`, `roles` [roleids], `unlock` (bool)
|
|
**Purpose:** Update a user; email uniqueness enforced; admins can also change active state, roles, and unlock the account; changes audit-logged.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/users/7 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"firstname":"Jane","unlock":true}'
|
|
```
|
|
|
|
### DELETE /api/users/<userid>
|
|
**Auth:** JWT + role `admin`
|
|
**Params:** path: `userid` (cannot be your own account)
|
|
**Purpose:** Delete a user; revokes their API tokens and detaches (nulls `userid` on) their audit-log rows first.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/users/7 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/users/permissions
|
|
**Auth:** JWT
|
|
**Params:** none
|
|
**Purpose:** List assignable permissions (core + enabled plugins) both flat and grouped by category, for the role grid.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/users/permissions -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/users/roles
|
|
**Auth:** JWT
|
|
**Params:** none
|
|
**Purpose:** List all roles with description, color, user count, permission names, and `isadmin` flag.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/users/roles -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### POST /api/users/roles
|
|
**Auth:** JWT + role `admin`
|
|
**Params:** body: `rolename` (required), `description`, `color`, `permissions` [names]
|
|
**Purpose:** Create a role and assign permissions by name; 409 if `rolename` exists.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/users/roles -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"rolename":"viewer","permissions":["assets.view"]}'
|
|
```
|
|
|
|
### PUT /api/users/roles/<roleid>
|
|
**Auth:** JWT + role `admin`
|
|
**Params:** path: `roleid`; body: `description`, `color`, `permissions` [names] (permissions immutable on the admin role)
|
|
**Purpose:** Update a role's description/color/permissions; admin role's permission set cannot be modified; audit-logged.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/users/roles/3 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"color":"#0057b8","permissions":["assets.view","assets.edit"]}'
|
|
```
|
|
|
|
### DELETE /api/users/roles/<roleid>
|
|
**Auth:** JWT + role `admin`
|
|
**Params:** path: `roleid`
|
|
**Purpose:** Delete a role; refuses for the admin role or any role still assigned to users.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/users/roles/3 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/apitokens
|
|
**Auth:** JWT
|
|
**Params:** query: `all=true` (admin only, lists everyone's tokens with owner info)
|
|
**Purpose:** List the caller's own API tokens (never returns hashes or secrets); admins may list all.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/apitokens?all=true' -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### POST /api/apitokens
|
|
**Auth:** JWT + permission `apitokens.create`
|
|
**Params:** body: `name` (required), `expiresat` (date/datetime), `scopes` [permission names, ceiling = owner's permissions], `resourcescopes` [resource names, plugin-defined]
|
|
**Purpose:** Create a personal API token for the caller; the full secret is returned once in this response and never again.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/apitokens -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"name":"import-script","scopes":["assets.edit"],"expiresat":"2026-12-31"}'
|
|
```
|
|
|
|
### PUT /api/apitokens/<tokenid>
|
|
**Auth:** JWT + permission `apitokens.create` (own token, or any if admin)
|
|
**Params:** path: `tokenid`; body: `name`, `isactive` (bool), `scopes` [names, validated against the token owner's permissions], `resourcescopes` [names]
|
|
**Purpose:** Rename, rescope, or (de)activate a token; scope ceiling is always the owner, even when an admin edits.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/apitokens/4 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"isactive":false}'
|
|
```
|
|
|
|
### DELETE /api/apitokens/<tokenid>
|
|
**Auth:** JWT + permission `apitokens.create` (own token, or any if admin)
|
|
**Params:** path: `tokenid`
|
|
**Purpose:** Revoke (deactivate, not delete) a token; audit-logged.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/apitokens/4 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/setup/needs-admin
|
|
**Auth:** none
|
|
**Params:** none
|
|
**Purpose:** Return `{needsadmin: true}` when zero users exist, so the login screen can offer first-run setup.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/setup/needs-admin
|
|
```
|
|
|
|
### POST /api/setup/create-admin
|
|
**Auth:** none (only functions while zero users exist; 403 afterwards)
|
|
**Params:** body: `username`, `email`, `password` (all required)
|
|
**Purpose:** Bootstrap the very first admin account (creates the admin role if missing).
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/setup/create-admin -H 'Content-Type: application/json' -d '{"username":"admin","email":"admin@example.com","password":"ChangeMe123"}'
|
|
```
|
|
|
|
### POST /api/setup/seed-reference
|
|
**Auth:** JWT + role `admin`
|
|
**Params:** none
|
|
**Purpose:** Idempotently seed core reference data, permissions, and default settings (runs the flask seed CLI routines).
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/setup/seed-reference -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### POST /api/setup/seed-starter
|
|
**Auth:** JWT + role `admin`
|
|
**Params:** none
|
|
**Purpose:** Idempotently add a starter list of common hardware vendors (Dell, HP, Lenovo, ...).
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/setup/seed-starter -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### POST /api/setup/complete
|
|
**Auth:** JWT + role `admin`
|
|
**Params:** none
|
|
**Purpose:** Set the `setup_complete` setting to true, marking the first-run wizard finished.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/setup/complete -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/settings
|
|
**Auth:** JWT optional
|
|
**Params:** query: `category` (filter)
|
|
**Purpose:** List settings; unauthenticated callers see only the public allowlist (branding+map categories plus named bootstrap keys); secrets always masked as `********`.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/settings?category=branding'
|
|
```
|
|
|
|
### POST /api/settings
|
|
**Auth:** JWT + permission `settings.edit`
|
|
**Params:** body: `key` (required), `value`, `valuetype` (default string), `category` (default general), `description`
|
|
**Purpose:** Create a new setting; 409 if the key exists.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/settings -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"key":"facility_name","value":"West Jefferson","category":"site"}'
|
|
```
|
|
|
|
### GET /api/settings/<key>
|
|
**Auth:** JWT optional
|
|
**Params:** path: `key`
|
|
**Purpose:** Get one setting; non-public keys return 404 (not 403) to unauthenticated callers; secret values masked.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/settings/facility_name
|
|
```
|
|
|
|
### PUT /api/settings/<key>
|
|
**Auth:** JWT + permission `settings.edit`
|
|
**Params:** path: `key`; body: `value` (required; bool coerced to 'true'/'false'; secret mask `********` means leave unchanged)
|
|
**Purpose:** Update a setting (upserts a plugin-scoped string row if the key is new); audit-logged with secrets masked; invalidates the 5-min settings cache.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/settings/facility_name -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"value":"West Jefferson"}'
|
|
```
|
|
|
|
### POST /api/settings/seed
|
|
**Auth:** JWT + permission `settings.edit`
|
|
**Params:** none
|
|
**Purpose:** Idempotently create any missing default settings (identifier toggles, search toggles, map, SMTP, SAML, etc.).
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/settings/seed -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### POST /api/settings/test-email
|
|
**Auth:** JWT + permission `settings.edit`
|
|
**Params:** body: `to` (optional; falls back to `alert_recipients` setting)
|
|
**Purpose:** Send a test email to verify SMTP config; always 200 with a `sent` flag, SMTP errors returned with credentials scrubbed.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/settings/test-email -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"to":"me@example.com"}'
|
|
```
|
|
|
|
### POST /api/settings/map-blueprint
|
|
**Auth:** JWT + role `admin`
|
|
**Params:** multipart/form-data: `file` (png/jpg/jpeg/gif/webp/svg), `theme=light|dark`
|
|
**Purpose:** Upload a floor-map blueprint image to the instance maps dir and point `map_blueprint_<theme>` at its served URL.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/settings/map-blueprint -H "Authorization: Bearer $TOK" -F 'file=@floor.png' -F 'theme=light'
|
|
```
|
|
|
|
### GET /api/settings/map-blueprint/<path:filename>
|
|
**Auth:** none
|
|
**Params:** path: `filename`
|
|
**Purpose:** Serve an uploaded floor-map blueprint image (public so kiosk dashboards can load it).
|
|
|
|
```bash
|
|
curl -O http://localhost:5001/api/settings/map-blueprint/blueprint-light.png
|
|
```
|
|
|
|
### POST /api/settings/branding-logo
|
|
**Auth:** JWT + role `admin`
|
|
**Params:** multipart/form-data: `file` (map image types plus .ico), `kind=site|qr|badge|favicon`
|
|
**Purpose:** Upload a branding logo/favicon to the instance branding dir and set the matching branding setting (`site_logo`/`qr_logo`/`badge_logo`/`site_favicon`).
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/settings/branding-logo -H "Authorization: Bearer $TOK" -F 'file=@logo.svg' -F 'kind=site'
|
|
```
|
|
|
|
### GET /api/settings/branding/<path:filename>
|
|
**Auth:** none
|
|
**Params:** path: `filename`
|
|
**Purpose:** Serve an uploaded branding logo (public - kiosks and print pages read it).
|
|
|
|
```bash
|
|
curl -O http://localhost:5001/api/settings/branding/logo-site.svg
|
|
```
|
|
|
|
## core-catalog
|
|
|
|
### GET /api/assets/types
|
|
**Auth:** JWT optional
|
|
**Params:** `page`, `per_page`, `active=false` to include inactive
|
|
**Purpose:** List asset types (paginated, active-only by default).
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/assets/types?active=false
|
|
```
|
|
|
|
### GET /api/assets/types/<type_id>
|
|
**Auth:** JWT optional
|
|
**Params:** path: `type_id`
|
|
**Purpose:** Get one asset type.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/assets/types/1
|
|
```
|
|
|
|
### POST /api/assets/types
|
|
**Auth:** permission `assets.create`
|
|
**Params:** body: `assettype` (req), `pluginname`, `tablename`, `description`, `icon`, `color`
|
|
**Purpose:** Create asset type (409 on duplicate name).
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/assets/types -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"assettype":"Robot","icon":"mdi-robot"}'
|
|
```
|
|
|
|
### PUT /api/assets/types/<type_id>
|
|
**Auth:** permission `assets.edit`
|
|
**Params:** body: `description`, `icon`, `color`, `isactive`
|
|
**Purpose:** Update asset type display fields only (name/plugin/table are structural, not editable).
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/assets/types/1 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"color":"#ff0000"}'
|
|
```
|
|
|
|
### GET /api/assets/statuses
|
|
**Auth:** JWT optional
|
|
**Params:** `page`, `per_page`, `active=false`
|
|
**Purpose:** List asset statuses (paginated, active-only by default).
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/assets/statuses
|
|
```
|
|
|
|
### GET /api/assets/statuses/<status_id>
|
|
**Auth:** JWT optional
|
|
**Params:** path: `status_id`
|
|
**Purpose:** Get one asset status.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/assets/statuses/1
|
|
```
|
|
|
|
### POST /api/assets/statuses
|
|
**Auth:** permission `assets.create`
|
|
**Params:** body: `status` (req), `description`, `color`
|
|
**Purpose:** Create asset status (409 on duplicate).
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/assets/statuses -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"status":"In Repair","color":"#f90"}'
|
|
```
|
|
|
|
### PUT /api/assets/statuses/<status_id>
|
|
**Auth:** permission `assets.edit`
|
|
**Params:** body: `status`, `description`, `color`, `isactive`
|
|
**Purpose:** Update asset status (rename conflict-checked).
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/assets/statuses/2 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"isactive":false}'
|
|
```
|
|
|
|
### DELETE /api/assets/statuses/<status_id>
|
|
**Auth:** permission `assets.delete`
|
|
**Params:** path: `status_id`
|
|
**Purpose:** Hard-delete asset status; 409 if any asset still uses it.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/assets/statuses/9 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/assets/relationshiptypes
|
|
**Auth:** JWT optional
|
|
**Params:** none
|
|
**Purpose:** List relationship types incl. read-only `propagatesthrough` rails.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/assets/relationshiptypes
|
|
```
|
|
|
|
### POST /api/assets/relationshiptypes
|
|
**Auth:** permission `assets.create`
|
|
**Params:** body: `relationshiptype` (req), `description`, `color`, `isdirectional` (default true)
|
|
**Purpose:** Create relationship type (409 on duplicate).
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/assets/relationshiptypes -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"relationshiptype":"controls","isdirectional":true}'
|
|
```
|
|
|
|
### PUT /api/assets/relationshiptypes/<type_id>
|
|
**Auth:** permission `assets.edit`
|
|
**Params:** body: `relationshiptype`, `description`, `color`, `isdirectional`
|
|
**Purpose:** Update relationship type (rename conflict-checked).
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/assets/relationshiptypes/3 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"color":"#00f"}'
|
|
```
|
|
|
|
### DELETE /api/assets/relationshiptypes/<type_id>
|
|
**Auth:** permission `assets.delete`
|
|
**Params:** path: `type_id`
|
|
**Purpose:** Hard-delete relationship type; 409 while relationships use it.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/assets/relationshiptypes/3 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/assets
|
|
**Auth:** JWT optional
|
|
**Params:** `page`, `per_page`, `active`, `search` (assetnumber/name/serialnumber ilike), `type` (name), `typeid|type_id`, `statusid|status_id`, `locationid|location_id`, `businessunitid|businessunit_id`, `sort` (assetnumber|name|createddate|modifieddate), `dir` (asc|desc), `include_type_data`
|
|
**Purpose:** List assets with filtering, search, sorting, pagination.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/assets?type=machine&search=205&include_type_data=true'
|
|
```
|
|
|
|
### GET /api/assets/<asset_id>
|
|
**Auth:** JWT optional
|
|
**Params:** `include_type_data` (default true)
|
|
**Purpose:** Get one asset with full details.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/assets/42
|
|
```
|
|
|
|
### POST /api/assets
|
|
**Auth:** permission `assets.create`
|
|
**Params:** body: `assetnumber` (req), `assettypeid` (req), `name`, `serialnumber`, `statusid` (default 1), `locationid`, `businessunitid`, `mapx`, `mapy`, `notes`
|
|
**Purpose:** Create asset (duplicate assetnumber 409, assettypeid validated); honors `X-Import-Mode` timestamps.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/assets -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"assetnumber":"0205","assettypeid":1,"name":"Grinder 5"}'
|
|
```
|
|
|
|
### PUT /api/assets/<asset_id>
|
|
**Auth:** permission `assets.edit`
|
|
**Params:** body: `assetnumber`, `name`, `serialnumber`, `assettypeid`, `statusid`, `locationid`, `businessunitid`, `mapx`, `mapy`, `notes`, `isactive`
|
|
**Purpose:** Update asset (allowed fields incl. isactive); honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/assets/42 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"locationid":3}'
|
|
```
|
|
|
|
### DELETE /api/assets/<asset_id>
|
|
**Auth:** permission `assets.delete`
|
|
**Params:** path: `asset_id`
|
|
**Purpose:** Soft-delete asset (`isactive=false`).
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/assets/42 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/assets/lookup/<assetnumber>
|
|
**Auth:** JWT optional
|
|
**Params:** path: `assetnumber` (string)
|
|
**Purpose:** Look up an active asset by asset number (returns full type data).
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/assets/lookup/0205
|
|
```
|
|
|
|
### GET /api/assets/<asset_id>/relationships
|
|
**Auth:** JWT optional
|
|
**Params:** path: `asset_id`
|
|
**Purpose:** Get outgoing + incoming active relationships for an asset with partner asset dicts.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/assets/42/relationships
|
|
```
|
|
|
|
### POST /api/assets/relationships
|
|
**Auth:** permission `assets.create`
|
|
**Params:** body: `sourceassetid` (req), `targetassetid` (req), `relationshiptypeid` (req), `notes`; `X-Import-Mode` honored
|
|
**Purpose:** Create relationship, then fan out across symmetric propagation rails (Dualpath); response carries `propagated` + `propagatedcount`.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/assets/relationships -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"sourceassetid":10,"targetassetid":42,"relationshiptypeid":1}'
|
|
```
|
|
|
|
### DELETE /api/assets/relationships/<rel_id>
|
|
**Auth:** permission `assets.delete`
|
|
**Params:** path: `rel_id`
|
|
**Purpose:** Soft-delete one relationship row (no cascade to propagated partner rows).
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/assets/relationships/7 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/assets/map
|
|
**Auth:** JWT optional
|
|
**Params:** `assettype` (name), `subtype` (id, per-type), `businessunitid`, `statusid`, `locationid`, `search`
|
|
**Purpose:** Unified floor-map payload: all mapped assets (with type data, primary IP, dualpath collapse) plus filter option lists.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/assets/map?assettype=machine&statusid=1'
|
|
```
|
|
|
|
### GET /api/assets/<asset_id>/communications
|
|
**Auth:** JWT optional
|
|
**Params:** path: `asset_id`
|
|
**Purpose:** List active communications (IPs etc.) for an asset with `comtype_name`.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/assets/42/communications
|
|
```
|
|
|
|
### GET /api/locations/types
|
|
**Auth:** JWT optional
|
|
**Params:** `active=false` includes inactive
|
|
**Purpose:** List location types.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/locations/types
|
|
```
|
|
|
|
### POST /api/locations/types
|
|
**Auth:** admin
|
|
**Params:** body: `locationtype` (req), `description`, `color`
|
|
**Purpose:** Create location type; reactivates a soft-deleted same-name type instead of 409.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/locations/types -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"locationtype":"Operation"}'
|
|
```
|
|
|
|
### PUT /api/locations/types/<type_id>
|
|
**Auth:** admin
|
|
**Params:** body: `locationtype`, `description`, `color`, `isactive`
|
|
**Purpose:** Update location type (rename conflict-checked).
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/locations/types/2 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"color":"#0a0"}'
|
|
```
|
|
|
|
### DELETE /api/locations/types/<type_id>
|
|
**Auth:** admin
|
|
**Params:** path: `type_id`
|
|
**Purpose:** Hard-delete location type; 409 while locations use it.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/locations/types/2 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/locations
|
|
**Auth:** JWT optional
|
|
**Params:** `page`, `per_page`, `active`, `locationname` (exact), `search` (name/building ilike)
|
|
**Purpose:** List locations (paginated); exact locationname lookup for idempotent import.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/locations?locationname=Building%201'
|
|
```
|
|
|
|
### GET /api/locations/<location_id>
|
|
**Auth:** JWT optional
|
|
**Params:** path: `location_id`
|
|
**Purpose:** Get one location.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/locations/3
|
|
```
|
|
|
|
### POST /api/locations
|
|
**Auth:** admin
|
|
**Params:** body: `locationname` (req), `building`, `floor`, `room`, `description`, `locationtypeid`, `parentlocationid`, `mapimage`, `mapwidth`, `mapheight`
|
|
**Purpose:** Create location (409 on duplicate name); honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/locations -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"locationname":"Cell 12","building":"B1"}'
|
|
```
|
|
|
|
### PUT /api/locations/<location_id>
|
|
**Auth:** admin
|
|
**Params:** body: `locationname`, `building`, `floor`, `room`, `description`, `locationtypeid`, `parentlocationid`, `mapimage`, `mapwidth`, `mapheight`, `isactive`
|
|
**Purpose:** Update location (rename conflict-checked); honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/locations/3 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"room":"104"}'
|
|
```
|
|
|
|
### DELETE /api/locations/<location_id>
|
|
**Auth:** admin
|
|
**Params:** path: `location_id`
|
|
**Purpose:** Soft-delete location.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/locations/3 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/vendors
|
|
**Auth:** JWT optional
|
|
**Params:** `page`, `per_page`, `active`, `vendor` (exact), `search` (ilike)
|
|
**Purpose:** List vendors (paginated); exact vendor lookup for idempotent import.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/vendors?search=fanuc'
|
|
```
|
|
|
|
### GET /api/vendors/<vendor_id>
|
|
**Auth:** JWT optional
|
|
**Params:** path: `vendor_id`
|
|
**Purpose:** Get one vendor.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/vendors/5
|
|
```
|
|
|
|
### POST /api/vendors
|
|
**Auth:** admin
|
|
**Params:** body: `vendor` (req), `description`, `website`, `supportphone`, `supportemail`, `notes`
|
|
**Purpose:** Create vendor (409 on duplicate); honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/vendors -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"vendor":"Fanuc"}'
|
|
```
|
|
|
|
### PUT /api/vendors/<vendor_id>
|
|
**Auth:** admin
|
|
**Params:** body: `vendor`, `description`, `website`, `supportphone`, `supportemail`, `notes`, `isactive`
|
|
**Purpose:** Update vendor (rename conflict-checked); honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/vendors/5 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"website":"https://fanuc.com"}'
|
|
```
|
|
|
|
### DELETE /api/vendors/<vendor_id>
|
|
**Auth:** admin
|
|
**Params:** path: `vendor_id`
|
|
**Purpose:** Soft-delete vendor.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/vendors/5 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/models
|
|
**Auth:** JWT optional
|
|
**Params:** `page`, `per_page`, `active`, `vendor` (id), `modeltype` (id), `modelnumber` (exact), `search` (ilike)
|
|
**Purpose:** List vendor catalog models (paginated) with flattened vendor/modeltype names; exact modelnumber+vendor lookup for import.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/models?vendor=5&search=30i'
|
|
```
|
|
|
|
### GET /api/models/<model_id>
|
|
**Auth:** JWT optional
|
|
**Params:** path: `model_id`
|
|
**Purpose:** Get one model with nested vendor + modeltype dicts.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/models/12
|
|
```
|
|
|
|
### POST /api/models
|
|
**Auth:** admin
|
|
**Params:** body: `modelnumber` (req), `vendorid`, `modeltypeid`, `description`, `imageurl`, `documentationurl`, `notes`
|
|
**Purpose:** Create model (409 on duplicate modelnumber+vendorid); honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/models -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"modelnumber":"R-30iB","vendorid":5}'
|
|
```
|
|
|
|
### PUT /api/models/<model_id>
|
|
**Auth:** admin
|
|
**Params:** body: `modelnumber`, `vendorid`, `modeltypeid`, `description`, `imageurl`, `documentationurl`, `notes`, `isactive`
|
|
**Purpose:** Update model; honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/models/12 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"notes":"EOL 2027"}'
|
|
```
|
|
|
|
### DELETE /api/models/<model_id>
|
|
**Auth:** admin
|
|
**Params:** path: `model_id`
|
|
**Purpose:** Soft-delete model.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/models/12 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### POST /api/models/<model_id>/image
|
|
**Auth:** admin
|
|
**Params:** multipart/form-data: `file=<image>` (.png/.jpg/.jpeg/.gif/.webp/.svg)
|
|
**Purpose:** Upload/replace model photo (saved as `instance/modelimages/model-<id><ext>`, one per model); sets `imageurl`.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/models/12/image -H "Authorization: Bearer $TOK" -F file=@robot.jpg
|
|
```
|
|
|
|
### GET /api/models/image/<filename>
|
|
**Auth:** none
|
|
**Params:** path: `filename`
|
|
**Purpose:** Serve an uploaded model image (deliberately public - asset detail pages read it without auth).
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/models/image/model-12.jpg
|
|
```
|
|
|
|
### DELETE /api/models/<model_id>/image
|
|
**Auth:** admin
|
|
**Params:** path: `model_id`
|
|
**Purpose:** Clear `imageurl` and delete the uploaded file only if it lives under `/api/models/image/` (external URLs untouched).
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/models/12/image -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/modeltypes
|
|
**Auth:** JWT optional
|
|
**Params:** `page`, `per_page`, `active`, `category`, `modeltype` (exact), `search` (ilike)
|
|
**Purpose:** List model types (types the vendor MODELS catalog, not machines); exact modeltype lookup for import.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/modeltypes?category=Equipment'
|
|
```
|
|
|
|
### GET /api/modeltypes/<type_id>
|
|
**Auth:** JWT optional
|
|
**Params:** path: `type_id`
|
|
**Purpose:** Get one model type.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/modeltypes/2
|
|
```
|
|
|
|
### POST /api/modeltypes
|
|
**Auth:** admin
|
|
**Params:** body: `modeltype` (req), `category`, `description`, `icon`
|
|
**Purpose:** Create model type (409 on duplicate); category defaults to Equipment; honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/modeltypes -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"modeltype":"Controller"}'
|
|
```
|
|
|
|
### PUT /api/modeltypes/<type_id>
|
|
**Auth:** admin
|
|
**Params:** body: `modeltype`, `category`, `description`, `icon`, `isactive`
|
|
**Purpose:** Update model type (rename conflict-checked); honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/modeltypes/2 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"icon":"mdi-chip"}'
|
|
```
|
|
|
|
### DELETE /api/modeltypes/<type_id>
|
|
**Auth:** admin
|
|
**Params:** path: `type_id`
|
|
**Purpose:** Soft-delete model type; 409 while models use it.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/modeltypes/2 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/businessunits
|
|
**Auth:** JWT optional
|
|
**Params:** `page`, `per_page`, `active`, `businessunit` (exact), `search` (name/code ilike)
|
|
**Purpose:** List business units (paginated); exact businessunit lookup for import.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/businessunits
|
|
```
|
|
|
|
### GET /api/businessunits/<bu_id>
|
|
**Auth:** JWT optional
|
|
**Params:** path: `bu_id`
|
|
**Purpose:** Get one business unit with parent + children.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/businessunits/1
|
|
```
|
|
|
|
### POST /api/businessunits
|
|
**Auth:** admin
|
|
**Params:** body: `businessunit` (req), `code`, `description`, `parentid`
|
|
**Purpose:** Create business unit (409 on duplicate); honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/businessunits -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"businessunit":"Blades","code":"BLD"}'
|
|
```
|
|
|
|
### PUT /api/businessunits/<bu_id>
|
|
**Auth:** admin
|
|
**Params:** body: `businessunit`, `code`, `description`, `parentid`, `isactive`
|
|
**Purpose:** Update business unit (rename conflict-checked); honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/businessunits/1 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"code":"BL"}'
|
|
```
|
|
|
|
### DELETE /api/businessunits/<bu_id>
|
|
**Auth:** admin
|
|
**Params:** path: `bu_id`
|
|
**Purpose:** Soft-delete business unit.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/businessunits/1 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/operatingsystems
|
|
**Auth:** JWT optional
|
|
**Params:** `page`, `per_page`, `active`, `osname` (exact), `osversion` (exact), `search` (osname ilike)
|
|
**Purpose:** List operating systems (paginated); exact osname/osversion lookup for import.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/operatingsystems?osname=Windows%2011'
|
|
```
|
|
|
|
### GET /api/operatingsystems/<os_id>
|
|
**Auth:** JWT optional
|
|
**Params:** path: `os_id`
|
|
**Purpose:** Get one operating system.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/operatingsystems/4
|
|
```
|
|
|
|
### POST /api/operatingsystems
|
|
**Auth:** admin
|
|
**Params:** body: `osname` (req), `osversion`, `architecture`, `endoflife`
|
|
**Purpose:** Create OS (409 on duplicate osname+osversion); honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/operatingsystems -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"osname":"Windows 11","osversion":"24H2"}'
|
|
```
|
|
|
|
### PUT /api/operatingsystems/<os_id>
|
|
**Auth:** admin
|
|
**Params:** body: `osname`, `osversion`, `architecture`, `endoflife`, `isactive`
|
|
**Purpose:** Update OS; honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/operatingsystems/4 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"endoflife":"2031-10-14"}'
|
|
```
|
|
|
|
### DELETE /api/operatingsystems/<os_id>
|
|
**Auth:** admin
|
|
**Params:** path: `os_id`
|
|
**Purpose:** Soft-delete OS.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/operatingsystems/4 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/customfields
|
|
**Auth:** JWT optional
|
|
**Params:** `assettypeid` (int), `active=false` includes inactive
|
|
**Purpose:** List custom-field definitions, ordered by sortorder.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/customfields?assettypeid=1'
|
|
```
|
|
|
|
### POST /api/customfields
|
|
**Auth:** admin
|
|
**Params:** body: `assettypeid` (req), `label` (req), `datatype` (one of CUSTOM_FIELD_DATATYPES, default text), `fieldkey`, `options` (list or newline/comma text), `showondetail`, `showonform`, `searchable`, `sortorder`
|
|
**Purpose:** Create field definition; fieldkey auto-slugged from label; reactivates a soft-deleted same-key field instead of 409.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/customfields -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"assettypeid":1,"label":"Coolant Type","datatype":"select","options":["Oil","Water"]}'
|
|
```
|
|
|
|
### PUT /api/customfields/<fieldid>
|
|
**Auth:** admin
|
|
**Params:** body: `label`, `datatype`, `options`, `showondetail`, `showonform`, `isactive`, `searchable`, `sortorder`
|
|
**Purpose:** Update field definition (label/datatype/options/flags/sortorder).
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/customfields/7 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"searchable":true}'
|
|
```
|
|
|
|
### DELETE /api/customfields/<fieldid>
|
|
**Auth:** admin
|
|
**Params:** path: `fieldid`
|
|
**Purpose:** Hard-delete field definition AND all stored values for it.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/customfields/7 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/customfields/asset/<assetid>
|
|
**Auth:** JWT optional
|
|
**Params:** path: `assetid`
|
|
**Purpose:** Active field defs for the asset's type merged with the asset's stored values.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/customfields/asset/42
|
|
```
|
|
|
|
### PUT /api/customfields/asset/<assetid>
|
|
**Auth:** admin
|
|
**Params:** body: `{values: {fieldid: value, ...}}`
|
|
**Purpose:** Upsert per-asset values; empty string clears a value; only fields of the asset's type accepted.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/customfields/asset/42 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"values":{"7":"Oil"}}'
|
|
```
|
|
|
|
### GET /api/supportteams
|
|
**Auth:** JWT optional
|
|
**Params:** `active`, `teamname` (exact)
|
|
**Purpose:** List support teams with contacts; exact teamname lookup for import (not paginated).
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/supportteams
|
|
```
|
|
|
|
### GET /api/supportteams/<team_id>
|
|
**Auth:** JWT optional
|
|
**Params:** path: `team_id`
|
|
**Purpose:** Get one support team with contacts.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/supportteams/2
|
|
```
|
|
|
|
### POST /api/supportteams
|
|
**Auth:** admin
|
|
**Params:** body: `teamname` (req), `teamurl`, `webhookurl`, `isactive`
|
|
**Purpose:** Create support team (409 on duplicate); audit-logged; honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/supportteams -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"teamname":"CNC Support"}'
|
|
```
|
|
|
|
### PUT /api/supportteams/<team_id>
|
|
**Auth:** admin
|
|
**Params:** body: `teamname`, `teamurl`, `webhookurl`, `isactive`
|
|
**Purpose:** Update support team (rename conflict-checked); audit-logged; honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/supportteams/2 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"webhookurl":"https://hooks/x"}'
|
|
```
|
|
|
|
### DELETE /api/supportteams/<team_id>
|
|
**Auth:** admin
|
|
**Params:** path: `team_id`
|
|
**Purpose:** Hard-delete team (cascade removes contacts); 409 while applications reference it; audit-logged.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/supportteams/2 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### POST /api/supportteams/<team_id>/contacts
|
|
**Auth:** admin
|
|
**Params:** body: `name` (req), `sso`, `sortorder`, `isactive`
|
|
**Purpose:** Add contact to a team; audit-logged; honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/supportteams/2/contacts -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"name":"Jane Doe","sso":"212345678"}'
|
|
```
|
|
|
|
### PUT /api/supportteams/<team_id>/contacts/<contact_id>
|
|
**Auth:** admin
|
|
**Params:** body: `name`, `sso`, `sortorder`, `isactive`
|
|
**Purpose:** Update a team contact; audit-logged; honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/supportteams/2/contacts/9 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"sortorder":1}'
|
|
```
|
|
|
|
### DELETE /api/supportteams/<team_id>/contacts/<contact_id>
|
|
**Auth:** admin
|
|
**Params:** path: `team_id`, `contact_id`
|
|
**Purpose:** Hard-delete a team contact; audit-logged.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/supportteams/2/contacts/9 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/applications
|
|
**Auth:** JWT optional
|
|
**Params:** `page`, `per_page`, `active`, `showhidden`, `installable` (true/false), `appname` (exact), `search` (name/description ilike)
|
|
**Purpose:** List applications (paginated) with installedcount; hidden apps excluded unless `showhidden=true`; exact appname lookup for import.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/applications?installable=true'
|
|
```
|
|
|
|
### GET /api/applications/<app_id>
|
|
**Auth:** JWT optional
|
|
**Params:** path: `app_id`
|
|
**Purpose:** Get one application with active versions, installedcount, and linked KB articles.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/applications/15
|
|
```
|
|
|
|
### POST /api/applications
|
|
**Auth:** permission `applications.create`
|
|
**Params:** body: `appname` (req), `appdescription`, `supportteamid`, `isinstallable`, `applicationnotes`, `installpath`, `applicationlink`, `documentationpath`, `ishidden`, `isprinter`, `islicenced`, `isrequired`, `image`
|
|
**Purpose:** Create application (409 on duplicate name); audit-logged; honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/applications -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"appname":"PC-DMIS","isinstallable":true}'
|
|
```
|
|
|
|
### PUT /api/applications/<app_id>
|
|
**Auth:** permission `applications.edit`
|
|
**Params:** body: any of `appname`, `appdescription`, `supportteamid`, `isinstallable`, `applicationnotes`, `installpath`, `applicationlink`, `documentationpath`, `ishidden`, `isprinter`, `islicenced`, `isrequired`, `image`, `isactive`
|
|
**Purpose:** Update application (rename conflict-checked); field-level change diff audit-logged; honors `X-Import-Mode`.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/applications/15 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"supportteamid":2}'
|
|
```
|
|
|
|
### DELETE /api/applications/<app_id>
|
|
**Auth:** permission `applications.delete`
|
|
**Params:** path: `app_id`
|
|
**Purpose:** Soft-delete application; audit-logged.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/applications/15 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### GET /api/applications/<app_id>/versions
|
|
**Auth:** JWT optional
|
|
**Params:** path: `app_id`
|
|
**Purpose:** List active versions of an application (desc).
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/applications/15/versions
|
|
```
|
|
|
|
### POST /api/applications/<app_id>/versions
|
|
**Auth:** permission `applications.create`
|
|
**Params:** body: `version` (req), `releasedate`, `notes`
|
|
**Purpose:** Create app version (409 on duplicate version per app); honors `X-Import-Mode` for legacy dates.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/applications/15/versions -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"version":"2024.2"}'
|
|
```
|
|
|
|
### GET /api/applications/<app_id>/installed
|
|
**Auth:** JWT optional
|
|
**Params:** path: `app_id`
|
|
**Purpose:** List computers with this app installed (503 if computers plugin absent).
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/applications/15/installed
|
|
```
|
|
|
|
### GET /api/applications/machines/<machine_id>
|
|
**Auth:** JWT optional
|
|
**Params:** path: `machine_id`
|
|
**Purpose:** List apps installed on a computer (machine_id is a computerid; 503 without computers plugin).
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/applications/machines/8
|
|
```
|
|
|
|
### POST /api/applications/machines/<machine_id>
|
|
**Auth:** permission `applications.create`
|
|
**Params:** body: `appid` (req), `appversionid`
|
|
**Purpose:** Install an app on a computer; reactivates a prior soft-deleted install; 409 if already installed.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/applications/machines/8 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"appid":15}'
|
|
```
|
|
|
|
### DELETE /api/applications/machines/<machine_id>/<app_id>
|
|
**Auth:** permission `applications.delete`
|
|
**Params:** path: `machine_id`, `app_id`
|
|
**Purpose:** Uninstall (soft-delete install row) an app from a computer.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/applications/machines/8/15 -H "Authorization: Bearer $TOK"
|
|
```
|
|
|
|
### PUT /api/applications/machines/<machine_id>/<app_id>
|
|
**Auth:** permission `applications.edit`
|
|
**Params:** body: `appversionid`
|
|
**Purpose:** Update an installed-app row (change appversionid).
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/applications/machines/8/15 -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"appversionid":3}'
|
|
```
|
|
|
|
## core-platform
|
|
|
|
### GET /api/reports
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** List all available reports (6 core cards plus cards contributed by enabled plugins via the get_reports hook).
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/reports
|
|
```
|
|
|
|
### GET /api/reports/machines-by-type
|
|
**Auth:** jwt-optional
|
|
**Params:** `businessunitid` (int filter), `format=json|csv`
|
|
**Purpose:** Machine count grouped by machine type (dualpath secondary bays collapsed when the site setting is on); 404 if machines plugin absent.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/reports/machines-by-type?businessunitid=2&format=csv'
|
|
```
|
|
|
|
### GET /api/reports/assets-by-status
|
|
**Auth:** jwt-optional
|
|
**Params:** `assettypeid`, `businessunitid`, `format=json|csv`
|
|
**Purpose:** Asset count grouped by status with status colors.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/reports/assets-by-status?assettypeid=1'
|
|
```
|
|
|
|
### GET /api/reports/kb-popularity
|
|
**Auth:** jwt-optional
|
|
**Params:** `limit` (default 20, max 100), `format=json|csv`
|
|
**Purpose:** Most-clicked knowledge base articles; 503 if knowledgebase plugin absent.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/reports/kb-popularity?limit=10'
|
|
```
|
|
|
|
### GET /api/reports/software-compliance
|
|
**Auth:** jwt-optional
|
|
**Params:** `appid` (filter to one app), `format=json|csv`
|
|
**Purpose:** Required applications vs installed per PC with compliance rate and up to 100 non-compliant PCs per app; 503 if computers plugin absent.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/reports/software-compliance?appid=5'
|
|
```
|
|
|
|
### GET /api/reports/asset-inventory
|
|
**Auth:** jwt-optional
|
|
**Params:** `businessunitid`, `locationid`, `format=json|csv`
|
|
**Purpose:** Complete asset inventory summary broken down by type, status, and location.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/reports/asset-inventory?locationid=3&format=csv'
|
|
```
|
|
|
|
### GET /api/reports/pc-relationships
|
|
**Auth:** jwt-optional
|
|
**Params:** `format=json|csv`
|
|
**Purpose:** PC-to-shop-floor-machine relationships (machine number, vendor, model, hostname, IP) matched in both edge directions via raw SQL UNION.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/reports/pc-relationships?format=csv'
|
|
```
|
|
|
|
### POST /api/reports/email
|
|
**Auth:** jwt + permission:reports.export
|
|
**Params:** body: `subject`, `columns` `[{key,label}]`, `rows` `[{..}]`, `intro` (optional), `to` (optional email)
|
|
**Purpose:** Email a report's rows as an HTML table on demand; recipient defaults to the site Alert Recipients setting; intended cron target via a PAT scoped to reports.export.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/reports/email -H 'Authorization: Bearer $PAT' -H 'Content-Type: application/json' -d '{"subject":"Warranty Report","columns":[{"key":"vendor","label":"Vendor"}],"rows":[{"vendor":"Haas"}],"to":"ops@example.com"}'
|
|
```
|
|
|
|
### GET /api/search
|
|
**Auth:** jwt-optional
|
|
**Params:** `q` (required, 2-200 chars)
|
|
**Purpose:** Global search across assets, applications, KB, employees, notifications, custom fields, hostnames, IPs/subnets, vendor/model/type; ServiceNOW ticket prefixes and smart redirects; results capped at 50, types filterable via `search_<type>_enabled` settings.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/search?q=tsgwp00525'
|
|
```
|
|
|
|
### GET /api/dashboard
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** Dashboard summary: asset counts by type (machines/PCs/network/printers/measuring tools, dualpath-collapsed), counts by status, 10 most recent assets.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/dashboard
|
|
```
|
|
|
|
### GET /api/dashboard/summary
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** Alias route for the same dashboard summary handler as GET /api/dashboard.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/dashboard/summary
|
|
```
|
|
|
|
### GET /api/dashboard/stats
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** Asset counts grouped by every asset type with display category labels.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/dashboard/stats
|
|
```
|
|
|
|
### GET /api/dashboard/navigation
|
|
**Auth:** none
|
|
**Params:** none
|
|
**Purpose:** Sidebar navigation items: core entries merged with get_navigation_items from every enabled plugin, sorted by position.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/dashboard/navigation
|
|
```
|
|
|
|
### GET /api/dashboard/widgets
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** Dashboard widget definitions aggregated from enabled plugins (get_dashboard_widgets hook), sorted by position.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/dashboard/widgets
|
|
```
|
|
|
|
### GET /api/dashboard/health
|
|
**Auth:** none
|
|
**Params:** none
|
|
**Purpose:** Health check: runs SELECT 1 against the DB, returns ok/degraded plus app version.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/dashboard/health
|
|
```
|
|
|
|
### GET /api/dashboarddefaults/visitor-location
|
|
**Auth:** none
|
|
**Params:** `fqdn` (optional), `ipaddress` (optional, defaults to client IP)
|
|
**Purpose:** Resolve the business unit for a kiosk/lobby display by FQDN first then IP (caller IP used when ipaddress omitted); null businessunitid when unmapped.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/dashboarddefaults/visitor-location?fqdn=display01.wjs.geaerospace.net'
|
|
```
|
|
|
|
### GET /api/dashboarddefaults/display-role
|
|
**Auth:** none
|
|
**Params:** `fqdn` (optional), `ipaddress` (optional, defaults to client IP)
|
|
**Purpose:** Resolve what a display PC should show at boot: role (dashboard/lobby/partskiosk), frontend path, and business unit; null role when unmapped.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/dashboarddefaults/display-role?ipaddress=10.1.2.3'
|
|
```
|
|
|
|
### GET /api/dashboarddefaults
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** List all active display-to-business-unit mappings.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/dashboarddefaults
|
|
```
|
|
|
|
### POST /api/dashboarddefaults
|
|
**Auth:** jwt + role:admin
|
|
**Params:** body: `fqdn`, `ipaddress`, `displayrole` (dashboard|lobby|partskiosk, default dashboard), `businessunitid`, `description`
|
|
**Purpose:** Create a display mapping; requires fqdn or ipaddress, dashboard role requires businessunitid, 409 on duplicate fqdn/IP; audit-logged.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/dashboarddefaults -H 'Authorization: Bearer $JWT' -H 'Content-Type: application/json' -d '{"ipaddress":"10.1.2.3","displayrole":"dashboard","businessunitid":2}'
|
|
```
|
|
|
|
### PUT /api/dashboarddefaults/<int:default_id>
|
|
**Auth:** jwt + role:admin
|
|
**Params:** body: any of `fqdn`, `ipaddress`, `displayrole`, `businessunitid`, `description`
|
|
**Purpose:** Update a display mapping; non-dashboard roles get businessunitid nulled, dashboard role must keep one.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/dashboarddefaults/7 -H 'Authorization: Bearer $JWT' -H 'Content-Type: application/json' -d '{"displayrole":"lobby"}'
|
|
```
|
|
|
|
### DELETE /api/dashboarddefaults/<int:default_id>
|
|
**Auth:** jwt + role:admin
|
|
**Params:** none
|
|
**Purpose:** Soft-delete (deactivate) a display mapping.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/dashboarddefaults/7 -H 'Authorization: Bearer $JWT'
|
|
```
|
|
|
|
### POST /api/collector/<pluginname>
|
|
**Auth:** api-key (X-API-Key: per-plugin `COLLECTOR_API_KEY_<NAME>` or shared `COLLECTOR_API_KEY`, or a collector.ingest-scoped managed PAT via Bearer/X-API-Key)
|
|
**Params:** body: JSON payload whose schema identityfield (e.g. hostname) is required; rest is plugin-defined
|
|
**Purpose:** Generic collector ingest (ADR-006): schema-validated identity field, idempotent upsert via the plugin's apply_collector_payload; audit-logged; 404 when no collector registered for the plugin.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/collector/computers -H 'X-API-Key: $KEY' -H 'Content-Type: application/json' -d '{"hostname":"tsgwp00525","serialnumber":"ABC123"}'
|
|
```
|
|
|
|
### GET /api/collector/_schemas
|
|
**Auth:** jwt
|
|
**Params:** none
|
|
**Purpose:** List collector schemas for all enabled plugins that accept collector input.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/collector/_schemas -H 'Authorization: Bearer $JWT'
|
|
```
|
|
|
|
### POST /api/collector/pc
|
|
**Auth:** api-key
|
|
**Params:** body: `hostname` (required), `lastboottime` (ISO), `currentuser`, `serialnumber`
|
|
**Purpose:** Legacy computers-specific ingest: update one PC matched by hostname (or asset number) - lastreporteddate, lastboottime, loggedinuser, serialnumber.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/collector/pc -H 'X-API-Key: $KEY' -H 'Content-Type: application/json' -d '{"hostname":"tsgwp00525","currentuser":"212345678"}'
|
|
```
|
|
|
|
### POST /api/collector/apps
|
|
**Auth:** api-key
|
|
**Params:** body: `hostname` (required), `apps` `[{appname, version}]` (required)
|
|
**Purpose:** Update installed applications for one PC; only apps already in the Application table are tracked, others skipped; returns created/updated/skipped counts.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/collector/apps -H 'X-API-Key: $KEY' -H 'Content-Type: application/json' -d '{"hostname":"tsgwp00525","apps":[{"appname":"PC-DMIS","version":"2023.2"}]}'
|
|
```
|
|
|
|
### POST /api/collector/heartbeat
|
|
**Auth:** api-key
|
|
**Params:** body: `hostname` (string) or `hostnames` (array)
|
|
**Purpose:** Record PC online heartbeat (single hostname or batch); stamps lastreporteddate, returns updated count and notfound list.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/collector/heartbeat -H 'X-API-Key: $KEY' -H 'Content-Type: application/json' -d '{"hostnames":["pc1","pc2"]}'
|
|
```
|
|
|
|
### POST /api/collector/bulk
|
|
**Auth:** api-key
|
|
**Params:** body: `pcs` `[{hostname (required), currentuser, lastboottime}]`
|
|
**Purpose:** Bulk update many PCs in one call (lastreporteddate, currentuser, lastboottime per entry); returns updated/notfound/errors.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/collector/bulk -H 'X-API-Key: $KEY' -H 'Content-Type: application/json' -d '{"pcs":[{"hostname":"pc1","currentuser":"212345678"}]}'
|
|
```
|
|
|
|
### GET /api/collector/status
|
|
**Auth:** api-key
|
|
**Params:** none
|
|
**Purpose:** Collector API liveness/credential check; returns timestamp and the collector endpoint list.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/collector/status -H 'X-API-Key: $KEY'
|
|
```
|
|
|
|
### GET /api/auditlogs
|
|
**Auth:** jwt + permission:audit.view
|
|
**Params:** `page` (default 1), `perpage` (default 50, max 200), `action` (created|updated|deleted), `entitytype`, `userid` (int), `search` (entityname/username ilike), `from_date`, `to_date` (ISO)
|
|
**Purpose:** List audit logs with filtering and pagination, newest first; rows enriched with best-effort SSO-to-full-name resolution.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/auditlogs?action=deleted&perpage=100' -H 'Authorization: Bearer $JWT'
|
|
```
|
|
|
|
### GET /api/auditlogs/entity/<entitytype>/<int:entityid>
|
|
**Auth:** jwt + permission:audit.view
|
|
**Params:** path only
|
|
**Purpose:** Full audit history for one entity, newest first.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/auditlogs/entity/Asset/42 -H 'Authorization: Bearer $JWT'
|
|
```
|
|
|
|
### GET /api/auditlogs/stats
|
|
**Auth:** jwt + permission:audit.view
|
|
**Params:** none
|
|
**Purpose:** Audit statistics: counts by action and entity type, last-7-days activity count, top 5 most active users.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/auditlogs/stats -H 'Authorization: Bearer $JWT'
|
|
```
|
|
|
|
### GET /api/plugins
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** List all discovered plugins (enabled or not) with metadata plus the framework contract version.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/plugins
|
|
```
|
|
|
|
### GET /api/plugins/enabled
|
|
**Auth:** none (jwt-optional decorator, no claims used)
|
|
**Params:** none
|
|
**Purpose:** Flat sorted array of enabled plugin names (registry read, no DB); deliberately anonymous so kiosk routes can gate plugin-owned frontend routes.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/plugins/enabled
|
|
```
|
|
|
|
### PUT /api/plugins/<name>
|
|
**Auth:** jwt + role:admin
|
|
**Params:** body: `enabled` (bool, required)
|
|
**Purpose:** Enable or disable a plugin (route changes need an app restart); 409 when unknown or a dependency conflict refuses the change.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/plugins/warranty -H 'Authorization: Bearer $JWT' -H 'Content-Type: application/json' -d '{"enabled":false}'
|
|
```
|
|
|
|
### GET /api/pluginui/settings-cards
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** Merge enabled plugins' settings-catalog cards (get_settings_cards hook) sorted by position for the settings rail/overview.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/pluginui/settings-cards
|
|
```
|
|
|
|
### GET /api/pluginui/asset-panels
|
|
**Auth:** jwt-optional
|
|
**Params:** `assetid` (int, required); 400 without it, 404 if asset missing
|
|
**Purpose:** Asset-detail panels from enabled plugins (get_asset_panels hook) matching one asset's type ('*' wildcard supported), sorted by position.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/pluginui/asset-panels?assetid=42'
|
|
```
|
|
|
|
### GET /api/pluginui/map-overlays
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** Merge enabled plugins' map overlay declarations (get_map_overlays hook), sorted by position.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/pluginui/map-overlays
|
|
```
|
|
|
|
### GET /api/pluginui/asset-presentation
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** Merge enabled plugins' asset-type presentation entries (icon + detail route per type) used by search rows and cross-links.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/pluginui/asset-presentation
|
|
```
|
|
|
|
## plugin-computers
|
|
|
|
### GET /api/computers/types
|
|
**Auth:** jwt-optional
|
|
**Params:** `page`, `per_page`, `active` (default true; `'false'` includes inactive), `search` (ilike on computertype)
|
|
**Purpose:** List computer types, paginated, active-only by default.
|
|
```bash
|
|
curl -H 'Authorization: Bearer $TOKEN' 'http://localhost:5001/api/computers/types?search=kiosk&per_page=50'
|
|
```
|
|
|
|
### GET /api/computers/types/<int:type_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** `type_id` in path
|
|
**Purpose:** Get a single computer type by ID.
|
|
```bash
|
|
curl 'http://localhost:5001/api/computers/types/3'
|
|
```
|
|
|
|
### POST /api/computers/types
|
|
**Auth:** permission `computers.create` (jwt_required)
|
|
**Params:** body: `computertype` (required), `description`, `icon`, `color`. Matching a deactivated type revives it instead of 409.
|
|
**Purpose:** Create (or reactivate) a computer type.
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"computertype":"Shopfloor","color":"#0066cc"}' 'http://localhost:5001/api/computers/types'
|
|
```
|
|
|
|
### PUT /api/computers/types/<int:type_id>
|
|
**Auth:** permission `computers.edit` (jwt_required)
|
|
**Params:** body: `computertype`, `description`, `icon`, `color`, `isactive`. 409 on duplicate name.
|
|
**Purpose:** Update a computer type.
|
|
```bash
|
|
curl -X PUT -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"isactive":false}' 'http://localhost:5001/api/computers/types/3'
|
|
```
|
|
|
|
### DELETE /api/computers/types/<int:type_id>
|
|
**Auth:** permission `computers.delete` (jwt_required)
|
|
**Params:** `type_id` in path. 409 if any Computer still uses the type.
|
|
**Purpose:** Hard-delete a computer type when unused.
|
|
```bash
|
|
curl -X DELETE -H 'Authorization: Bearer $TOKEN' 'http://localhost:5001/api/computers/types/3'
|
|
```
|
|
|
|
### GET /api/computers/protocols
|
|
**Auth:** jwt-optional
|
|
**Params:** `active` (default true; `'false'` includes disabled)
|
|
**Purpose:** List remote-access protocols (VNC/WinRM/RDP catalog), unpaginated.
|
|
```bash
|
|
curl 'http://localhost:5001/api/computers/protocols?active=false'
|
|
```
|
|
|
|
### POST /api/computers/protocols
|
|
**Auth:** permission `computers.edit` (jwt_required)
|
|
**Params:** body: `name`, `scheme`, `linktemplate` (all required), `defaultport`, `isactive`. 409 on duplicate name.
|
|
**Purpose:** Create an access protocol.
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"name":"VNC","scheme":"vnc","defaultport":5900,"linktemplate":"vnc://{host}:{port}"}' 'http://localhost:5001/api/computers/protocols'
|
|
```
|
|
|
|
### PUT|PATCH /api/computers/protocols/<int:protocol_id>
|
|
**Auth:** permission `computers.edit` (jwt_required)
|
|
**Params:** body: `name`, `scheme`, `linktemplate`, `defaultport`, `isactive` (all optional)
|
|
**Purpose:** Update an access protocol.
|
|
```bash
|
|
curl -X PATCH -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"defaultport":5901}' 'http://localhost:5001/api/computers/protocols/2'
|
|
```
|
|
|
|
### DELETE /api/computers/protocols/<int:protocol_id>
|
|
**Auth:** permission `computers.edit` (jwt_required)
|
|
**Params:** `protocol_id` in path. If referenced by any ComputerAccess it deactivates instead of deleting.
|
|
**Purpose:** Delete an access protocol (soft-deactivate when in use).
|
|
```bash
|
|
curl -X DELETE -H 'Authorization: Bearer $TOKEN' 'http://localhost:5001/api/computers/protocols/2'
|
|
```
|
|
|
|
### GET /api/computers/display-kiosks
|
|
**Auth:** jwt-optional
|
|
**Params:** none. Uses pctype mapping for `gea-shopfloor-display` (default "Kiosk") and the `display_fqdn_domain` setting.
|
|
**Purpose:** List display-kiosk computers with derived `F<serial>.<domain>` FQDN for the Dashboard Defaults picker.
|
|
```bash
|
|
curl -H 'Authorization: Bearer $TOKEN' 'http://localhost:5001/api/computers/display-kiosks'
|
|
```
|
|
|
|
### GET /api/computers
|
|
**Auth:** jwt-optional
|
|
**Params:** `page`, `per_page`, `active`, `search` (assetnumber/name/serialnumber/hostname ilike), `assetnumber` (exact, for idempotent import), `typeid`|`type_id`, `osid`|`os_id`, `locationid`|`location_id`, `businessunitid`|`businessunit_id`, `shopfloor` (true/false), `sort` (hostname|assetnumber|name|lastreporteddate), `dir` (asc|desc)
|
|
**Purpose:** List computers (asset + computer + resolved access links), filtered and paginated.
|
|
```bash
|
|
curl 'http://localhost:5001/api/computers?shopfloor=true&sort=lastreporteddate&dir=desc&per_page=25'
|
|
```
|
|
|
|
### GET /api/computers/<int:computer_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** `computer_id` in path
|
|
**Purpose:** Get one computer with full detail: asset fields, computer extension, communications, resolved access links.
|
|
```bash
|
|
curl 'http://localhost:5001/api/computers/42'
|
|
```
|
|
|
|
### GET /api/computers/by-asset/<int:asset_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** `asset_id` in path
|
|
**Purpose:** Get computer record by its core asset ID.
|
|
```bash
|
|
curl 'http://localhost:5001/api/computers/by-asset/1234'
|
|
```
|
|
|
|
### GET /api/computers/by-hostname/<hostname>
|
|
**Auth:** jwt-optional
|
|
**Params:** `hostname` in path (exact match)
|
|
**Purpose:** Get computer record by hostname.
|
|
```bash
|
|
curl 'http://localhost:5001/api/computers/by-hostname/tsgwp00525'
|
|
```
|
|
|
|
### POST /api/computers
|
|
**Auth:** permission `computers.create` (jwt_required)
|
|
**Params:** body: `assetnumber` (required); `name`, `serialnumber`, `gaugelabreference`, `maintenancereference`, `statusid`, `locationid`, `businessunitid`, `mapx`, `mapy`, `notes`, `computertypeid`, `hostname`, `osid`, `vendorid`, `modelnumberid`, `loggedinuser`, `lastreporteddate`, `lastboottime`, `ipaddress` (creates primary IP communication), `accessmethods` `[{protocolid, portoverride?}]`. `X-Import-Mode` header preserves legacy timestamps. 409 on duplicate assetnumber or hostname.
|
|
**Purpose:** Create a computer (Asset + Computer records, optional primary IP and access methods), audit-logged.
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"assetnumber":"PC-0042","hostname":"tsgwp00042","computertypeid":1,"osid":2,"ipaddress":"10.1.2.3","accessmethods":[{"protocolid":1}]}' 'http://localhost:5001/api/computers'
|
|
```
|
|
|
|
### PUT /api/computers/<int:computer_id>
|
|
**Auth:** permission `computers.edit` (jwt_required)
|
|
**Params:** body: any asset field (`assetnumber`, `name`, `serialnumber`, `gaugelabreference`, `maintenancereference`, `statusid`, `locationid`, `businessunitid`, `mapx`, `mapy`, `notes`, `isactive`) or computer field (`computertypeid`, `hostname`, `osid`, `vendorid`, `modelnumberid`, `loggedinuser`, `lastreporteddate`, `lastboottime`). `ipaddress` upserts/clears the primary IP communication; `accessmethods` replaces the protocol list. 409 on assetnumber/hostname conflict. Changes audit-logged.
|
|
**Purpose:** Update a computer's asset and extension fields.
|
|
```bash
|
|
curl -X PUT -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"locationid":7,"ipaddress":"10.1.2.4"}' 'http://localhost:5001/api/computers/42'
|
|
```
|
|
|
|
### DELETE /api/computers/<int:computer_id>
|
|
**Auth:** permission `computers.delete` (jwt_required)
|
|
**Params:** `computer_id` in path
|
|
**Purpose:** Soft-delete a computer (sets asset `isactive=false`), audit-logged.
|
|
```bash
|
|
curl -X DELETE -H 'Authorization: Bearer $TOKEN' 'http://localhost:5001/api/computers/42'
|
|
```
|
|
|
|
### GET /api/computers/<int:computer_id>/apps
|
|
**Auth:** jwt-optional
|
|
**Params:** `computer_id` in path. Returns active installs only.
|
|
**Purpose:** List installed applications on a computer.
|
|
```bash
|
|
curl 'http://localhost:5001/api/computers/42/apps'
|
|
```
|
|
|
|
### POST /api/computers/<int:computer_id>/apps
|
|
**Auth:** permission `computers.create` (jwt_required)
|
|
**Params:** body: `appid` (required, must exist in Applications), `appversionid`. Reactivates a soft-deleted install; 409 if already installed.
|
|
**Purpose:** Record an application install on a computer.
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"appid":17,"appversionid":3}' 'http://localhost:5001/api/computers/42/apps'
|
|
```
|
|
|
|
### DELETE /api/computers/<int:computer_id>/apps/<int:app_id>
|
|
**Auth:** permission `computers.delete` (jwt_required)
|
|
**Params:** `computer_id` and `app_id` in path
|
|
**Purpose:** Soft-remove an installed application (`isactive=false`).
|
|
```bash
|
|
curl -X DELETE -H 'Authorization: Bearer $TOKEN' 'http://localhost:5001/api/computers/42/apps/17'
|
|
```
|
|
|
|
### POST /api/computers/<int:computer_id>/report
|
|
**Auth:** permission `computers.create` (jwt_required)
|
|
**Params:** body (all optional): `loggedinuser`, `lastboottime`. Server sets `lastreporteddate` to now (UTC).
|
|
**Purpose:** Agent status check-in: refresh last-reported timestamp plus logged-in user and boot time.
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"loggedinuser":"cproudlock","lastboottime":"2026-07-30T06:00:00"}' 'http://localhost:5001/api/computers/42/report'
|
|
```
|
|
|
|
### GET /api/computers/dashboard/summary
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** Dashboard counts: total active computers, breakdown by type and OS, shopfloor vs non-shopfloor.
|
|
```bash
|
|
curl 'http://localhost:5001/api/computers/dashboard/summary'
|
|
```
|
|
|
|
## plugin-employees
|
|
|
|
### GET /api/employees/search
|
|
|
|
**Auth:** none
|
|
**Params:** `q` (query string, min 2 chars, required), `limit` (max results, default 10, capped 50)
|
|
**Purpose:** Search employees by first name, last name, or SSO substring (self-hosted table or external HR DB depending on `employee_directory_mode` setting).
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/employees/search?q=smith&limit=5'
|
|
```
|
|
|
|
### GET /api/employees/lookup/<sso>
|
|
|
|
**Auth:** none
|
|
**Params:** `sso` (path, numeric)
|
|
**Purpose:** Look up a single employee by numeric SSO; returns directory fields plus resolved `photourl`.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/employees/lookup/210009518'
|
|
```
|
|
|
|
### GET /api/employees/lookup
|
|
|
|
**Auth:** none
|
|
**Params:** `sso` (query, comma-separated numeric SSOs, at least one required)
|
|
**Purpose:** Bulk lookup of multiple employees by SSO list; returns `employees` array plus a joined names string.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/employees/lookup?sso=210009518,210001234'
|
|
```
|
|
|
|
### GET /api/employees/directory
|
|
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** List the full self-hosted directory for the management page; 400 when directory mode is external.
|
|
|
|
```bash
|
|
curl -H 'Authorization: Bearer $TOKEN' 'http://localhost:5001/api/employees/directory'
|
|
```
|
|
|
|
### POST /api/employees/directory
|
|
|
|
**Auth:** jwt + require_role admin
|
|
**Params:** JSON body: `sso` (numeric, required), `firstname`, `lastname` (required), `team`, `role`, `picture` (also accepts external-style keys `SSO`/`First_Name`/`Last_Name`/`Team`/`Role`/`Picture`)
|
|
**Purpose:** Create a self-hosted directory employee; 409 if SSO exists, 400 in external mode.
|
|
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"sso":210009518,"firstname":"Jane","lastname":"Doe","team":"CNC","role":"Machinist"}' 'http://localhost:5001/api/employees/directory'
|
|
```
|
|
|
|
### PUT /api/employees/directory/<int:sso>
|
|
|
|
**Auth:** jwt + require_role admin
|
|
**Params:** `sso` (path); JSON body: `firstname`, `lastname`, `team`, `role`, `picture` (external-style keys also accepted; `team`/`role`/`picture` can be cleared)
|
|
**Purpose:** Update a self-hosted directory employee's name/team/role/picture; 404 if missing, 400 in external mode.
|
|
|
|
```bash
|
|
curl -X PUT -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"team":"Quality"}' 'http://localhost:5001/api/employees/directory/210009518'
|
|
```
|
|
|
|
### DELETE /api/employees/directory/<int:sso>
|
|
|
|
**Auth:** jwt + require_role admin
|
|
**Params:** `sso` (path)
|
|
**Purpose:** Delete a self-hosted directory employee; 404 if missing, 400 in external mode.
|
|
|
|
```bash
|
|
curl -X DELETE -H 'Authorization: Bearer $TOKEN' 'http://localhost:5001/api/employees/directory/210009518'
|
|
```
|
|
|
|
### POST /api/employees/directory/import
|
|
|
|
**Auth:** jwt + require_role admin
|
|
**Params:** multipart `file=<csv>` OR JSON body `{"csv": "..."}`; rows missing numeric sso or names are skipped
|
|
**Purpose:** Bulk upsert the self-hosted directory from CSV (headers `SSO,First_Name,Last_Name,Team,Role,Picture` case-insensitive; plain `firstname`/`lastname` also accepted); returns added/updated/skipped counts.
|
|
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $TOKEN' -F 'file=@employees.csv' 'http://localhost:5001/api/employees/directory/import'
|
|
```
|
|
|
|
### POST /api/employees/<int:sso>/photo
|
|
|
|
**Auth:** jwt + require_role admin
|
|
**Params:** `sso` (path); multipart/form-data `file=<image>`, extensions .png/.jpg/.jpeg/.gif/.webp only
|
|
**Purpose:** Upload or replace a self-hosted employee's photo (saved as `photo-<sso><ext>` in instance employeephotos dir; old file wiped even on extension change); 409 in external mode, 404 if employee missing.
|
|
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $TOKEN' -F 'file=@jane.jpg' 'http://localhost:5001/api/employees/210009518/photo'
|
|
```
|
|
|
|
### GET /api/employees/photo/<path:filename>
|
|
|
|
**Auth:** none
|
|
**Params:** `filename` (path, e.g. `photo-210009518.jpg`)
|
|
**Purpose:** Serve an uploaded employee photo file from the instance employeephotos dir (public so kiosk recognition cards can read it).
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/employees/photo/photo-210009518.jpg'
|
|
```
|
|
|
|
### DELETE /api/employees/<int:sso>/photo
|
|
|
|
**Auth:** jwt + require_role admin
|
|
**Params:** `sso` (path)
|
|
**Purpose:** Clear a self-hosted employee's photo record and delete the uploaded file; 409 in external mode, 404 if employee missing.
|
|
|
|
```bash
|
|
curl -X DELETE -H 'Authorization: Bearer $TOKEN' 'http://localhost:5001/api/employees/210009518/photo'
|
|
```
|
|
|
|
## plugin-geenforce
|
|
|
|
### GET /api/geenforce/manifest
|
|
**Auth:** api-key (managed service token with `geenforce.fetch` scope via `X-API-Key` or Bearer PAT) OR source IP in `geenforce_allowed_cidrs`; resource-bound tokens restricted to their listed scopes (403 otherwise)
|
|
**Params:** query: `pctype` (required, = scopename), `phase` (default `runtime`); header: `If-None-Match` for 304
|
|
**Purpose:** Serve the current PUBLISHED manifest JSON snapshot for a scope (never the live draft) to the GE-Enforce client, with ETag/304 support and `X-Manifest-Version` header.
|
|
|
|
```bash
|
|
curl -H 'X-API-Key: $TOKEN' 'http://localhost:5001/api/geenforce/manifest?pctype=cmm&phase=runtime'
|
|
```
|
|
|
|
### GET /api/geenforce/payload/<sha256>
|
|
**Auth:** api-key (`geenforce.fetch` service token) OR IP allowlist; resource-bound tokens get 404 for blobs not referenced by their scopes
|
|
**Params:** path: `sha256` (64 lowercase hex chars, 400 otherwise); header: `If-None-Match` (ETag = the hash)
|
|
**Purpose:** Download a payload blob by content hash (blob store first, then inline DB payload) so share-less PCs can pull installers over HTTPS; per-IP rate limited (120/60s default) and size-capped (512MB default, 413 above).
|
|
|
|
```bash
|
|
curl -H 'X-API-Key: $TOKEN' -o installer.exe 'http://localhost:5001/api/geenforce/payload/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
|
|
```
|
|
|
|
### POST /api/geenforce/report
|
|
**Auth:** api-key (managed service token with `geenforce.report` scope) OR IP allowlist
|
|
**Params:** JSON body: `hostname` (required); remainder parsed by `service.record_enforcement_report` (`scopename`, `phase`, `appliedversion`, `enforcerversion`, `status`, per-entry results, counts); 400 on ValueError
|
|
**Purpose:** Record one PC's enforcement cycle: applied manifest version plus per-entry self-heal outcomes (installed/skipped/failed); returns `reportid` + `status`.
|
|
|
|
```bash
|
|
curl -X POST -H 'X-API-Key: $TOKEN' -H 'Content-Type: application/json' -d '{"hostname":"tsgwp00525","scopename":"cmm","appliedversion":4,"results":[{"entryname":"7zip","action":"installed"}]}' http://localhost:5001/api/geenforce/report
|
|
```
|
|
|
|
### GET /api/geenforce/scopes
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** none
|
|
**Purpose:** List all imaging PC-type scopes with entry counts and current published version numbers, ordered by phase then scopename.
|
|
|
|
```bash
|
|
curl -H 'Authorization: Bearer $JWT' http://localhost:5001/api/geenforce/scopes
|
|
```
|
|
|
|
### POST /api/geenforce/scopes
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** JSON body: `scopename` (required), `phase` (default `runtime`, must be in PHASES), `manifestversion` (default `1.0`), `description`, `computertypeid`, `measuringtooltypeid`, `iscommon` (defaults true when scopename == `common`)
|
|
**Purpose:** Create a new manifest scope; 400 if scopename missing, phase invalid, or scope already exists for that scopename+phase; returns 201 with scope summary.
|
|
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $JWT' -H 'Content-Type: application/json' -d '{"scopename":"cmm","phase":"runtime","description":"CMM bays"}' http://localhost:5001/api/geenforce/scopes
|
|
```
|
|
|
|
### GET /api/geenforce/scopes/<int:scopeid>
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** path: `scopeid`
|
|
**Purpose:** Get one scope's summary plus its full draft entry list (each entry includes entryid, sortorder, curated appid/appname link, and inline-payload metadata).
|
|
|
|
```bash
|
|
curl -H 'Authorization: Bearer $JWT' http://localhost:5001/api/geenforce/scopes/3
|
|
```
|
|
|
|
### PUT /api/geenforce/scopes/<int:scopeid>
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** JSON body (all optional): `description`, `computertypeid`, `measuringtooltypeid`, `manifestversion` (stringified), `iscommon` (bool-coerced)
|
|
**Purpose:** Update scope metadata fields (only keys present in the body are changed); scopename and phase are immutable here.
|
|
|
|
```bash
|
|
curl -X PUT -H 'Authorization: Bearer $JWT' -H 'Content-Type: application/json' -d '{"description":"updated","manifestversion":"1.1"}' http://localhost:5001/api/geenforce/scopes/3
|
|
```
|
|
|
|
### DELETE /api/geenforce/scopes/<int:scopeid>
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** path: `scopeid`
|
|
**Purpose:** Delete a scope (and via cascade its entries); returns `{deleted: scopeid}`.
|
|
|
|
```bash
|
|
curl -X DELETE -H 'Authorization: Bearer $JWT' http://localhost:5001/api/geenforce/scopes/3
|
|
```
|
|
|
|
### GET /api/geenforce/scopes/<int:scopeid>/preview
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** path: `scopeid`
|
|
**Purpose:** Render the DRAFT manifest JSON that a publish would freeze, for admin review before shipping.
|
|
|
|
```bash
|
|
curl -H 'Authorization: Bearer $JWT' http://localhost:5001/api/geenforce/scopes/3/preview
|
|
```
|
|
|
|
### GET /api/geenforce/applications
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** none
|
|
**Purpose:** List the core active Applications catalog (appid + appname) for the curated entry-to-app link picker in the entry editor.
|
|
|
|
```bash
|
|
curl -H 'Authorization: Bearer $JWT' http://localhost:5001/api/geenforce/applications
|
|
```
|
|
|
|
### POST /api/geenforce/scopes/<int:scopeid>/entries
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** path: `scopeid`; JSON body: `Name` (required), `Type` (required, one of ENTRY_TYPES), optional `appid` (curated app link, unknown/non-numeric ids ignored), plus manifest fields consumed by `build_entry` (PCTypes, TargetHostnames, DetectionValue, etc.)
|
|
**Purpose:** Create a manifest entry in a scope at the next sortorder; validates Name (required) and Type (must be in ENTRY_TYPES); 400 on duplicate Name in scope; returns 201 with entry payload.
|
|
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $JWT' -H 'Content-Type: application/json' -d '{"Name":"7-Zip","Type":"App","appid":12}' http://localhost:5001/api/geenforce/scopes/3/entries
|
|
```
|
|
|
|
### PUT /api/geenforce/entries/<int:entryid>
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** path: `entryid`; JSON body: `Name` (required), `Type` (required), optional `appid`, plus manifest fields
|
|
**Purpose:** Replace an entry's fields from the payload (re-populates via `populate_entry`, re-creating the one-to-one InUseCheck); same Name/Type validation and duplicate-Name 400 as create.
|
|
|
|
```bash
|
|
curl -X PUT -H 'Authorization: Bearer $JWT' -H 'Content-Type: application/json' -d '{"Name":"7-Zip","Type":"App","DetectionValue":"24.08"}' http://localhost:5001/api/geenforce/entries/17
|
|
```
|
|
|
|
### DELETE /api/geenforce/entries/<int:entryid>
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** path: `entryid`
|
|
**Purpose:** Delete a manifest entry; returns `{deleted: entryid}`.
|
|
|
|
```bash
|
|
curl -X DELETE -H 'Authorization: Bearer $JWT' http://localhost:5001/api/geenforce/entries/17
|
|
```
|
|
|
|
### PUT /api/geenforce/scopes/<int:scopeid>/entries/reorder
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** path: `scopeid`; JSON body: `order` = [entryid, ...] (must match the scope's entry ids exactly, 400 otherwise)
|
|
**Purpose:** Set entry ordering from an entryid list.
|
|
|
|
```bash
|
|
curl -X PUT -H 'Authorization: Bearer $JWT' -H 'Content-Type: application/json' -d '{"order":[17,15,16]}' http://localhost:5001/api/geenforce/scopes/3/entries/reorder
|
|
```
|
|
|
|
### GET /api/geenforce/scopes/<int:scopeid>/simulate
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** path: `scopeid`; query (all optional): `pctype` (defaults to scopename), `subtype`, `hostname`, `machinenumber`, `cmmversion`; phase comes from the scope
|
|
**Purpose:** Simulate which draft entries would apply to a given machine profile and why the rest are filtered out (PCTypes/TargetHostnames/TargetMachineNumbers/_CmmVersion), using the engine-mirror filters.
|
|
|
|
```bash
|
|
curl -H 'Authorization: Bearer $JWT' 'http://localhost:5001/api/geenforce/scopes/3/simulate?hostname=tsgwp00525&cmmversion=2023.2'
|
|
```
|
|
|
|
### GET /api/geenforce/scopes/<int:scopeid>/compliance
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** path: `scopeid`
|
|
**Purpose:** Fleet install coverage per app-linked entry (installed/version-match counts from the computers plugin's ComputerInstalledApp; null counts with `computersplugin:false` when that plugin is absent).
|
|
|
|
```bash
|
|
curl -H 'Authorization: Bearer $JWT' http://localhost:5001/api/geenforce/scopes/3/compliance
|
|
```
|
|
|
|
### POST /api/geenforce/entries/<int:entryid>/payload
|
|
**Auth:** jwt + permission `geenforce.publish`
|
|
**Params:** path: `entryid`; multipart/form-data: `file` (required)
|
|
**Purpose:** Upload an inline payload file (max 1 MB, rejects empty) for an entry and point the entry at it (stores sha256, filename, mimetype); returns 201 with entry payload.
|
|
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $JWT' -F 'file=@fix.ps1' http://localhost:5001/api/geenforce/entries/17/payload
|
|
```
|
|
|
|
### GET /api/geenforce/entries/<int:entryid>/payload
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** path: `entryid`
|
|
**Purpose:** Download the stored inline payload bytes for an entry as an attachment (404 if the entry has no payload).
|
|
|
|
```bash
|
|
curl -H 'Authorization: Bearer $JWT' -o fix.ps1 http://localhost:5001/api/geenforce/entries/17/payload
|
|
```
|
|
|
|
### POST /api/geenforce/scopes/<int:scopeid>/publish
|
|
**Auth:** jwt + permission `geenforce.publish`
|
|
**Params:** path: `scopeid`; JSON body (optional): `notes`
|
|
**Purpose:** Freeze the scope's draft into a new published version (`service.publish_scope`), recording the publishing user from the JWT identity and optional notes; returns 201 with the new versionnumber.
|
|
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $JWT' -H 'Content-Type: application/json' -d '{"notes":"add 7zip 24.08"}' http://localhost:5001/api/geenforce/scopes/3/publish
|
|
```
|
|
|
|
### GET /api/geenforce/scopes/<int:scopeid>/versions
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** path: `scopeid`
|
|
**Purpose:** List published versions for a scope, newest first (versionnumber, iscurrent, publishedat, publishedby, notes).
|
|
|
|
```bash
|
|
curl -H 'Authorization: Bearer $JWT' http://localhost:5001/api/geenforce/scopes/3/versions
|
|
```
|
|
|
|
### GET /api/geenforce/scopes/<int:scopeid>/versions/<int:versionnumber>
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** path: `scopeid`, `versionnumber`
|
|
**Purpose:** Fetch one published version's frozen manifest JSON (parsed and returned in the success envelope).
|
|
|
|
```bash
|
|
curl -H 'Authorization: Bearer $JWT' http://localhost:5001/api/geenforce/scopes/3/versions/4
|
|
```
|
|
|
|
### POST /api/geenforce/scopes/<int:scopeid>/rollback
|
|
**Auth:** jwt + permission `geenforce.publish`
|
|
**Params:** path: `scopeid`; JSON body: `versionnumber` (required, int)
|
|
**Purpose:** Roll the scope's current published pointer back to an earlier versionnumber (`service.rollback_scope`); 400 with the error message if the version is invalid.
|
|
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $JWT' -H 'Content-Type: application/json' -d '{"versionnumber":3}' http://localhost:5001/api/geenforce/scopes/3/rollback
|
|
```
|
|
|
|
### POST /api/geenforce/scopes/<int:scopeid>/export-share
|
|
**Auth:** jwt + permission `geenforce.publish`
|
|
**Params:** path: `scopeid`; no body
|
|
**Purpose:** Write the scope's current published JSON to the configured share root (`geenforce_share_root` setting), backing up the old file to `_meta/history`; 400 if the share root is unconfigured or the export fails.
|
|
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $JWT' http://localhost:5001/api/geenforce/scopes/3/export-share
|
|
```
|
|
|
|
### GET /api/geenforce/config
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** none
|
|
**Purpose:** Read plugin config: the on-share export root (`geenforce_share_root`) and the client IP allowlist CIDRs (`geenforce_allowed_cidrs`).
|
|
|
|
```bash
|
|
curl -H 'Authorization: Bearer $JWT' http://localhost:5001/api/geenforce/config
|
|
```
|
|
|
|
### PUT /api/geenforce/config
|
|
**Auth:** jwt + permission `geenforce.publish`
|
|
**Params:** JSON body (both optional): `shareroot` (string path), `allowedcidrs` (CSV/newline CIDR list); allowedcidrs is validated/normalized (comma/newline-separated CIDRs or bare IPs, 400 listing any bad entries); only keys present in the body are written
|
|
**Purpose:** Update plugin config settings.
|
|
|
|
```bash
|
|
curl -X PUT -H 'Authorization: Bearer $JWT' -H 'Content-Type: application/json' -d '{"allowedcidrs":"10.20.30.0/24, 192.168.5.7"}' http://localhost:5001/api/geenforce/config
|
|
```
|
|
|
|
### GET /api/geenforce/reports
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** query (optional): `hostname` (ILIKE match), `scopename` (exact)
|
|
**Purpose:** Latest enforcement report per PC (iscurrent rows) for the fleet compliance view: applied vs latest published version (`receivedlatest` flag), install/skip/fail/filtered counts, status, check-in times.
|
|
|
|
```bash
|
|
curl -H 'Authorization: Bearer $JWT' 'http://localhost:5001/api/geenforce/reports?scopename=cmm'
|
|
```
|
|
|
|
### GET /api/geenforce/reports/<int:reportid>
|
|
**Auth:** jwt + permission `geenforce.manage`
|
|
**Params:** path: `reportid`
|
|
**Purpose:** One enforcement report in detail with per-entry outcomes (entryname, action, selfhealed, exitcode, message) plus applied-vs-latest version comparison.
|
|
|
|
```bash
|
|
curl -H 'Authorization: Bearer $JWT' http://localhost:5001/api/geenforce/reports/42
|
|
```
|
|
|
|
## plugin-knowledgebase
|
|
|
|
### GET /api/knowledgebase
|
|
|
|
**Auth:** jwt-optional
|
|
**Params:** query: `page`, `per_page`, `search` (ILIKE on shortdescription/keywords/application name), `appid` (int filter), `linkurl` (exact natural-key match), `shortdescription` (exact match), `sort` (`clicks|topic|description|lastupdated`, default `clicks`), `order` (`asc|desc`, default `desc`)
|
|
**Purpose:** List active KB articles with search, topic filter, natural-key lookup, sorting, and pagination; each item includes its linked application (appid/appname) or null.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/knowledgebase?search=printer&sort=clicks&order=desc&page=1&per_page=20'
|
|
```
|
|
|
|
### GET /api/knowledgebase/stats
|
|
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** Return aggregate stats for active articles: `totalclicks` (sum of clicks) and `totalarticles` (count).
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/knowledgebase/stats'
|
|
```
|
|
|
|
### GET /api/knowledgebase/<int:link_id>
|
|
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `link_id` (int)
|
|
**Purpose:** Fetch a single active article by id with its application (appid/appname) or null; 404 if missing or inactive.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/knowledgebase/42'
|
|
```
|
|
|
|
### POST /api/knowledgebase/<int:link_id>/click
|
|
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `link_id` (int); no body
|
|
**Purpose:** Increment the article's click counter and return the target `linkurl` plus new click count (used for redirect tracking); 404 if missing or inactive.
|
|
|
|
```bash
|
|
curl -X POST 'http://localhost:5001/api/knowledgebase/42/click'
|
|
```
|
|
|
|
### POST /api/knowledgebase
|
|
|
|
**Auth:** permission `kb.create` (jwt required)
|
|
**Params:** body JSON: `shortdescription` (required), `linkurl` (required), `appid` (optional int, must exist), `keywords` (optional); import-mode may pass timestamp fields
|
|
**Purpose:** Create a new KB article; validates required fields and that `appid` (if given) exists; honors `X-Import-Mode` timestamp preservation via `apply_import_timestamps`; returns 201.
|
|
|
|
```bash
|
|
curl -X POST 'http://localhost:5001/api/knowledgebase' -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"shortdescription":"VPN setup guide","linkurl":"https://wiki.example.com/vpn","appid":3,"keywords":"vpn,remote"}'
|
|
```
|
|
|
|
### PUT /api/knowledgebase/<int:link_id>
|
|
|
|
**Auth:** permission `kb.edit` (jwt required)
|
|
**Params:** path: `link_id` (int); body JSON: any of `shortdescription`, `linkurl`, `appid`, `keywords`, `isactive`
|
|
**Purpose:** Update an article's shortdescription, linkurl, appid, keywords, and/or isactive; validates `appid` if changed; honors import timestamps; 404 if article missing.
|
|
|
|
```bash
|
|
curl -X PUT 'http://localhost:5001/api/knowledgebase/42' -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"keywords":"vpn,zscaler","isactive":true}'
|
|
```
|
|
|
|
### DELETE /api/knowledgebase/<int:link_id>
|
|
|
|
**Auth:** permission `kb.delete` (jwt required)
|
|
**Params:** path: `link_id` (int)
|
|
**Purpose:** Soft-delete an article by setting `isactive=false` (row is retained); 404 if article missing.
|
|
|
|
```bash
|
|
curl -X DELETE 'http://localhost:5001/api/knowledgebase/42' -H 'Authorization: Bearer $TOKEN'
|
|
```
|
|
|
|
## plugin-machines
|
|
|
|
### GET /api/machines/types
|
|
**Auth:** jwt-optional
|
|
**Params:** query: `page`, `per_page`, `active` (pass `false` to include inactive), `search` (ilike on `machinetype`)
|
|
**Purpose:** List machine types (active by default) with pagination and name search.
|
|
```bash
|
|
curl 'http://localhost:5001/api/machines/types?search=cnc&page=1&per_page=25'
|
|
```
|
|
|
|
### GET /api/machines/types/<type_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `type_id` (int)
|
|
**Purpose:** Get a single machine type by ID.
|
|
```bash
|
|
curl 'http://localhost:5001/api/machines/types/3'
|
|
```
|
|
|
|
### POST /api/machines/types
|
|
**Auth:** jwt + permission:machines.create
|
|
**Params:** body: `machinetype` (required), `description`, `icon`, `color`
|
|
**Purpose:** Create a machine type; reactivates a soft-deleted type of the same name instead of returning 409.
|
|
```bash
|
|
curl -X POST 'http://localhost:5001/api/machines/types' -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"machinetype":"Lathe","description":"Turning machines","icon":"mdi-rotate-3d","color":"#1976d2"}'
|
|
```
|
|
|
|
### PUT /api/machines/types/<type_id>
|
|
**Auth:** jwt + permission:machines.edit
|
|
**Params:** path: `type_id`; body: any of `machinetype`, `description`, `icon`, `color`, `isactive`
|
|
**Purpose:** Update a machine type; rename guarded by 409 on duplicate name.
|
|
```bash
|
|
curl -X PUT 'http://localhost:5001/api/machines/types/3' -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"description":"5-axis mills","isactive":true}'
|
|
```
|
|
|
|
### DELETE /api/machines/types/<type_id>
|
|
**Auth:** jwt + permission:machines.delete
|
|
**Params:** path: `type_id` (int)
|
|
**Purpose:** Hard-delete a machine type; refused with 409 if any machine still references it.
|
|
```bash
|
|
curl -X DELETE 'http://localhost:5001/api/machines/types/3' -H 'Authorization: Bearer $TOKEN'
|
|
```
|
|
|
|
### GET /api/machines
|
|
**Auth:** jwt-optional
|
|
**Params:** query: `page`, `per_page`, `active` (`false` includes inactive), `assetnumber` (exact-match for idempotent import), `search` (assetnumber/name/serialnumber ilike), `typeid`|`type_id`, `vendorid`|`vendor_id`, `locationid`|`location_id`, `businessunitid`|`businessunit_id`, `sort` (`assetnumber`|`name`), `dir` (`asc`|`desc`)
|
|
**Purpose:** List machines (Asset+Machine join) with filters, sorting, pagination; collapses Dualpath dual-bay pairs to one row (annotated with `dualpathpartner`) when the site setting is enabled.
|
|
```bash
|
|
curl 'http://localhost:5001/api/machines?search=2007&typeid=2&sort=name&dir=desc&page=1&per_page=50'
|
|
```
|
|
|
|
### GET /api/machines/<machine_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `machine_id` (int)
|
|
**Purpose:** Get one machine with full asset details, nested machine dict, and `dualpathpartner` info.
|
|
```bash
|
|
curl 'http://localhost:5001/api/machines/42'
|
|
```
|
|
|
|
### GET /api/machines/by-asset/<asset_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `asset_id` (int)
|
|
**Purpose:** Get machine data looked up by core asset ID instead of machine ID.
|
|
```bash
|
|
curl 'http://localhost:5001/api/machines/by-asset/1001'
|
|
```
|
|
|
|
### POST /api/machines
|
|
**Auth:** jwt + permission:machines.create
|
|
**Params:** body: `assetnumber` (required, 409 on duplicate); asset fields: `name`, `gaugelabreference`, `maintenancereference`, `serialnumber`, `statusid` (default 1), `locationid`, `businessunitid`, `mapx`, `mapy`, `notes`; machine fields: `machinetypeid`, `vendorid`, `modelnumberid`, `requiresmanualconfig`, `islocationonly`, `lastmaintenancedate`, `nextmaintenancedate`, `maintenanceintervaldays`, `controllervendorid`, `controllermodelid`
|
|
**Purpose:** Create a machine (creates both core Asset row and Machine extension row); audit-logged; honors `X-Import-Mode` legacy timestamps via `apply_import_timestamps`.
|
|
```bash
|
|
curl -X POST 'http://localhost:5001/api/machines' -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"assetnumber":"2007","name":"Makino a51","machinetypeid":2,"vendorid":5,"locationid":3,"statusid":1}'
|
|
```
|
|
|
|
### PUT /api/machines/<machine_id>
|
|
**Auth:** jwt + permission:machines.edit
|
|
**Params:** path: `machine_id`; body: any of `assetnumber`, `name`, `gaugelabreference`, `maintenancereference`, `serialnumber`, `statusid`, `locationid`, `businessunitid`, `mapx`, `mapy`, `notes`, `isactive`, `machinetypeid`, `vendorid`, `modelnumberid`, `requiresmanualconfig`, `islocationonly`, `lastmaintenancedate`, `nextmaintenancedate`, `maintenanceintervaldays`, `controllervendorid`, `controllermodelid`
|
|
**Purpose:** Update machine (asset + machine fields) with per-field change tracking to AuditLog; 409 on assetnumber conflict.
|
|
```bash
|
|
curl -X PUT 'http://localhost:5001/api/machines/42' -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"locationid":7,"nextmaintenancedate":"2026-09-01"}'
|
|
```
|
|
|
|
### DELETE /api/machines/<machine_id>
|
|
**Auth:** jwt + permission:machines.delete
|
|
**Params:** path: `machine_id` (int)
|
|
**Purpose:** Soft-delete a machine (sets `asset.isactive=false`, keeps Machine row linked); audit-logged.
|
|
```bash
|
|
curl -X DELETE 'http://localhost:5001/api/machines/42' -H 'Authorization: Bearer $TOKEN'
|
|
```
|
|
|
|
### GET /api/machines/dashboard/summary
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** Dashboard summary: total active machine count plus counts grouped by machine type and by asset status (total and by-type exclude Dualpath secondary bays when the collapse setting is enabled; by-status does not).
|
|
```bash
|
|
curl 'http://localhost:5001/api/machines/dashboard/summary'
|
|
```
|
|
|
|
## plugin-measuringtools
|
|
|
|
### GET /api/measuringtools/types
|
|
**Auth:** jwt-optional
|
|
**Params:** query: `active` (default true; `'false'` includes inactive), `search` (name ilike), `page`, `perpage`
|
|
**Purpose:** List measuring-tool types (active-only by default), paginated, name-sorted.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/measuringtools/types?search=caliper&page=1&perpage=25'
|
|
```
|
|
|
|
### GET /api/measuringtools/types/<type_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `type_id` (int)
|
|
**Purpose:** Get one measuring-tool type by id (404 if missing).
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/measuringtools/types/3'
|
|
```
|
|
|
|
### POST /api/measuringtools/types
|
|
**Auth:** jwt + permission:measuringtools.create
|
|
**Params:** body JSON: `name` (required), `description`, `color`
|
|
**Purpose:** Create a measuring-tool type; reactivates a soft-deleted same-named one, 409 if an active one exists.
|
|
|
|
```bash
|
|
curl -X POST 'http://localhost:5001/api/measuringtools/types' -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"name":"Thread Gage","description":"Go/no-go thread gages","color":"#4caf50"}'
|
|
```
|
|
|
|
### PUT /api/measuringtools/types/<type_id>
|
|
**Auth:** jwt + permission:measuringtools.edit
|
|
**Params:** path: `type_id`; body JSON: `name`, `description`, `color`, `isactive` (only keys present are applied)
|
|
**Purpose:** Update a measuring-tool type; 409 on rename collision with an existing name.
|
|
|
|
```bash
|
|
curl -X PUT 'http://localhost:5001/api/measuringtools/types/3' -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"description":"Updated","isactive":true}'
|
|
```
|
|
|
|
### DELETE /api/measuringtools/types/<type_id>
|
|
**Auth:** jwt + permission:measuringtools.delete
|
|
**Params:** path: `type_id` (int)
|
|
**Purpose:** Hard-delete a measuring-tool type; refused with 409 if any tool still references it.
|
|
|
|
```bash
|
|
curl -X DELETE 'http://localhost:5001/api/measuringtools/types/3' -H 'Authorization: Bearer $TOKEN'
|
|
```
|
|
|
|
### GET /api/measuringtools
|
|
**Auth:** jwt-optional
|
|
**Params:** query: `active` (default true), `assetnumber` (exact match, for idempotent import), `search` (assetnumber/name/serialnumber ilike), `typeid`, `locationid`, `statusid`, `calibrationstatus` (overdue|duesoon|current|unknown), `page`, `perpage`
|
|
**Purpose:** List measuring tools (Asset core merged with extension), filtered + paginated; derived calibrationstatus filter applied post-pagination.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/measuringtools?typeid=2&calibrationstatus=overdue&page=1&perpage=50'
|
|
```
|
|
|
|
### GET /api/measuringtools/<tool_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `tool_id` (int)
|
|
**Purpose:** Get one measuring tool by measuringtoolid, asset core dict with extension nested under `measuringtool`.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/measuringtools/17'
|
|
```
|
|
|
|
### GET /api/measuringtools/by-asset/<asset_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `asset_id` (int)
|
|
**Purpose:** Get a measuring tool by its core assetid (404 if the asset has no extension row).
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/measuringtools/by-asset/1042'
|
|
```
|
|
|
|
### POST /api/measuringtools
|
|
**Auth:** jwt + permission:measuringtools.create
|
|
**Params:** body JSON: `assetnumber` (required, 409 on duplicate), `name`, `gaugelabreference`, `maintenancereference`, `serialnumber`, `statusid` (default 1), `locationid`, `businessunitid`, `mapx`, `mapy`, `notes`, `measuringtooltypeid`, `calibrationintervaldays`, `lastcalibrationdate` (YYYY-MM-DD), `nextcalibrationdate` (YYYY-MM-DD), `calibrationprovider`; import timestamps honored via `X-Import-Mode`
|
|
**Purpose:** Create a measuring tool: one Asset core row (assettype `measuring_tool`) plus one measuringtools extension row in a single payload; audit-logged.
|
|
|
|
```bash
|
|
curl -X POST 'http://localhost:5001/api/measuringtools' -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"assetnumber":"MT-0042","name":"6in Digital Caliper","measuringtooltypeid":2,"calibrationintervaldays":365,"lastcalibrationdate":"2026-01-15","nextcalibrationdate":"2027-01-15","calibrationprovider":"Gage Lab"}'
|
|
```
|
|
|
|
### PUT /api/measuringtools/<tool_id>
|
|
**Auth:** jwt + permission:measuringtools.edit
|
|
**Params:** path: `tool_id`; body JSON (only present keys applied): asset fields `assetnumber`, `name`, `gaugelabreference`, `maintenancereference`, `serialnumber`, `statusid`, `locationid`, `businessunitid`, `mapx`, `mapy`, `notes`, `isactive`; extension fields `measuringtooltypeid`, `calibrationintervaldays`, `calibrationprovider`, `notes`, `lastcalibrationdate`, `nextcalibrationdate` (YYYY-MM-DD)
|
|
**Purpose:** Update asset core fields and extension fields in one payload; 409 on assetnumber collision; changes audit-logged.
|
|
|
|
```bash
|
|
curl -X PUT 'http://localhost:5001/api/measuringtools/17' -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"locationid":5,"nextcalibrationdate":"2026-12-01"}'
|
|
```
|
|
|
|
### DELETE /api/measuringtools/<tool_id>
|
|
**Auth:** jwt + permission:measuringtools.delete
|
|
**Params:** path: `tool_id` (int)
|
|
**Purpose:** Soft-delete a measuring tool by setting its asset isactive=false; audit-logged.
|
|
|
|
```bash
|
|
curl -X DELETE 'http://localhost:5001/api/measuringtools/17' -H 'Authorization: Bearer $TOKEN'
|
|
```
|
|
|
|
### GET /api/measuringtools/map-overlay
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** ADR-010 map overlay: per-asset calibration badges `[{assetid, color, label}]` for active tools that are overdue or due soon only; no coordinates returned.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/measuringtools/map-overlay'
|
|
```
|
|
|
|
### GET /api/measuringtools/report/calibration
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** Calibration report for the Reports hub: counts and full tool lists bucketed by derived status (overdue/duesoon/current/unknown) plus statuscolors map.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/measuringtools/report/calibration'
|
|
```
|
|
|
|
## plugin-network
|
|
|
|
### GET /api/network/types
|
|
**Auth:** jwt-optional
|
|
**Params:** `page`, `per_page`, `active` (default true; `false` includes inactive), `search` (ilike on networkdevicetype)
|
|
**Purpose:** List network device types, paginated.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/network/types?search=switch&per_page=50'
|
|
```
|
|
|
|
### GET /api/network/types/<int:type_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `type_id`
|
|
**Purpose:** Get one network device type by ID.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/network/types/3
|
|
```
|
|
|
|
### POST /api/network/types
|
|
**Auth:** jwt + permission `network.create`
|
|
**Params:** body: `networkdevicetype` (required), `description`, `icon`, `color`
|
|
**Purpose:** Create a network device type. Reactivates a soft-deleted duplicate instead of returning 409.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/network/types -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"networkdevicetype":"Switch","icon":"mdi-switch","color":"#2196f3"}'
|
|
```
|
|
|
|
### PUT /api/network/types/<int:type_id>
|
|
**Auth:** jwt + permission `network.edit`
|
|
**Params:** body: `networkdevicetype`, `description`, `icon`, `color`, `isactive`
|
|
**Purpose:** Update a network device type. 409 on name collision.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/network/types/3 -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"description":"Access switches"}'
|
|
```
|
|
|
|
### DELETE /api/network/types/<int:type_id>
|
|
**Auth:** jwt + permission `network.delete`
|
|
**Params:** path: `type_id`
|
|
**Purpose:** Hard-delete a device type. 409 if any device still references it.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/network/types/3 -H "Authorization: Bearer $TOKEN"
|
|
```
|
|
|
|
### GET /api/network
|
|
**Auth:** jwt-optional
|
|
**Params:** `page`, `per_page`, `active`, `assetnumber` (exact match for idempotent import), `search` (assetnumber/name/serialnumber/hostname), `typeid`|`type_id`, `vendorid`|`vendor_id`, `locationid`|`location_id`, `businessunitid`|`businessunit_id`, `poe` (true/false), `managed` (true/false), `sort` (hostname|assetnumber|name), `dir` (asc|desc)
|
|
**Purpose:** List network devices (Asset joined with NetworkDevice extension plus primary IP), filtered, sorted, paginated.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/network?typeid=2&poe=true&sort=hostname&dir=asc'
|
|
```
|
|
|
|
### GET /api/network/<int:device_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `device_id` (networkdeviceid)
|
|
**Purpose:** Get one network device (asset dict + `networkdevice` sub-object + primary `ipaddress`).
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/network/17
|
|
```
|
|
|
|
### GET /api/network/by-asset/<int:asset_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `asset_id`
|
|
**Purpose:** Look up a network device by its core assetid.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/network/by-asset/1042
|
|
```
|
|
|
|
### GET /api/network/by-hostname/<hostname>
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `hostname`
|
|
**Purpose:** Look up a network device by exact hostname.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/network/by-hostname/wjf-sw-idf3-01
|
|
```
|
|
|
|
### POST /api/network
|
|
**Auth:** jwt + permission `network.create`
|
|
**Params:** body: `assetnumber` (required); `name`, `serialnumber`, `gaugelabreference`, `maintenancereference`, `statusid` (default 1), `locationid`, `businessunitid`, `mapx`, `mapy`, `notes`, `networkdevicetypeid`, `vendorid`, `hostname` (unique), `firmwareversion`, `portcount`, `ispoe`, `ismanaged`, `rackunit`, `ipaddress`
|
|
**Purpose:** Create a network device. Creates core Asset + NetworkDevice extension, upserts primary-IP Communication, audit-logged, honors `X-Import-Mode` legacy timestamps.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/network -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"assetnumber":"NET-0042","hostname":"wjf-sw-idf3-01","networkdevicetypeid":1,"portcount":48,"ispoe":true,"ipaddress":"10.1.3.10"}'
|
|
```
|
|
|
|
### PUT /api/network/<int:device_id>
|
|
**Auth:** jwt + permission `network.edit`
|
|
**Params:** body: any of `assetnumber`, `name`, `serialnumber`, `gaugelabreference`, `maintenancereference`, `statusid`, `locationid`, `businessunitid`, `mapx`, `mapy`, `notes`, `isactive`, `networkdevicetypeid`, `vendorid`, `hostname`, `firmwareversion`, `portcount`, `ispoe`, `ismanaged`, `rackunit`, `ipaddress`
|
|
**Purpose:** Update asset + network-device fields. 409 on assetnumber/hostname conflicts, change-diff audit log, upserts primary IP when `ipaddress` present.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/network/17 -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"firmwareversion":"16.12.4","ipaddress":"10.1.3.11"}'
|
|
```
|
|
|
|
### DELETE /api/network/<int:device_id>
|
|
**Auth:** jwt + permission `network.delete`
|
|
**Params:** path: `device_id`
|
|
**Purpose:** Soft-delete a network device (sets asset.isactive=false). Audit-logged.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/network/17 -H "Authorization: Bearer $TOKEN"
|
|
```
|
|
|
|
### GET /api/network/dashboard/summary
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** Dashboard counts: total active devices, by type, by vendor, PoE vs non-PoE.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/network/dashboard/summary
|
|
```
|
|
|
|
### GET /api/network/vlans
|
|
**Auth:** jwt-optional
|
|
**Params:** `page`, `per_page`, `active` (default true), `search` (name/description/vlannumber), `type` (exact vlantype)
|
|
**Purpose:** List VLANs, paginated, ordered by vlannumber.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/network/vlans?search=voice'
|
|
```
|
|
|
|
### GET /api/network/vlans/<int:vlan_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `vlan_id`
|
|
**Purpose:** Get one VLAN including its active subnets.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/network/vlans/5
|
|
```
|
|
|
|
### POST /api/network/vlans
|
|
**Auth:** jwt + permission `network.create`
|
|
**Params:** body: `vlannumber` (required), `name` (required), `description`, `vlantype`
|
|
**Purpose:** Create a VLAN. 409 on duplicate vlannumber. Audit-logged.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/network/vlans -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"vlannumber":120,"name":"Shopfloor","vlantype":"production"}'
|
|
```
|
|
|
|
### PUT /api/network/vlans/<int:vlan_id>
|
|
**Auth:** jwt + permission `network.edit`
|
|
**Params:** body: `vlannumber`, `name`, `description`, `vlantype`, `isactive`
|
|
**Purpose:** Update a VLAN. 409 on vlannumber conflict. Change-diff audit log.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/network/vlans/5 -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"description":"CNC cell VLAN"}'
|
|
```
|
|
|
|
### DELETE /api/network/vlans/<int:vlan_id>
|
|
**Auth:** jwt + permission `network.delete`
|
|
**Params:** path: `vlan_id`
|
|
**Purpose:** Soft-delete a VLAN. 400 if it still has active subnets. Audit-logged.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/network/vlans/5 -H "Authorization: Bearer $TOKEN"
|
|
```
|
|
|
|
### GET /api/network/subnets
|
|
**Auth:** jwt-optional
|
|
**Params:** `page`, `per_page`, `active` (default true), `search` (cidr/name/description), `vlanid`, `locationid`, `type` (exact subnettype)
|
|
**Purpose:** List subnets, paginated, ordered by cidr.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/network/subnets?vlanid=5'
|
|
```
|
|
|
|
### GET /api/network/subnets/<int:subnet_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `subnet_id`
|
|
**Purpose:** Get one subnet plus `devices`: every asset of any type (PC/printer/network) whose primary-IP Communication falls inside the CIDR, with cross-plugin detail URLs.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/network/subnets/2
|
|
```
|
|
|
|
### POST /api/network/subnets
|
|
**Auth:** jwt + permission `network.create`
|
|
**Params:** body: `cidr` (required, must contain `/`), `name` (required), `description`, `gatewayip`, `subnetmask`, `networkaddress`, `broadcastaddress`, `vlanid`, `subnettype`, `locationid`, `dhcpenabled` (default true), `dhcprangestart`, `dhcprangeend`, `dns1`, `dns2`
|
|
**Purpose:** Create a subnet. Validates CIDR notation and vlanid existence. 409 on duplicate cidr. Audit-logged.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/network/subnets -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"cidr":"10.1.3.0/24","name":"IDF3 access","vlanid":5,"gatewayip":"10.1.3.1"}'
|
|
```
|
|
|
|
### PUT /api/network/subnets/<int:subnet_id>
|
|
**Auth:** jwt + permission `network.edit`
|
|
**Params:** body: any of `cidr`, `name`, `description`, `gatewayip`, `subnetmask`, `networkaddress`, `broadcastaddress`, `vlanid`, `subnettype`, `locationid`, `dhcpenabled`, `dhcprangestart`, `dhcprangeend`, `dns1`, `dns2`, `isactive`
|
|
**Purpose:** Update a subnet. 409 on cidr conflict. Change-diff audit log.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/network/subnets/2 -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"dhcpenabled":false}'
|
|
```
|
|
|
|
### DELETE /api/network/subnets/<int:subnet_id>
|
|
**Auth:** jwt + permission `network.delete`
|
|
**Params:** path: `subnet_id`
|
|
**Purpose:** Soft-delete a subnet (isactive=false). Audit-logged.
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/network/subnets/2 -H "Authorization: Bearer $TOKEN"
|
|
```
|
|
|
|
## plugin-notifications
|
|
|
|
### GET /api/notifications/types
|
|
|
|
**Auth:** none
|
|
**Params:** `page`, `per_page`; `active=false` to include inactive types
|
|
**Purpose:** List notification types, paginated, active-only by default.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/notifications/types?active=false&page=1&per_page=50'
|
|
```
|
|
|
|
### POST /api/notifications/types
|
|
|
|
**Auth:** JWT + permission `notifications.create`
|
|
**Params:** body: `typename` (required, unique), `typedescription`/`description`, `typecolor`/`color`, `expirymode` (`none`|`duration`|`dailytime`), `expirydays`, `expiryhour`, `expiryminute`, `splitperemployee`, `showemployeephoto`, `displaystyle` (`standard`|`carousel`|`grid`|`banner`)
|
|
**Purpose:** Create a notification type including expiry rule and shopfloor display config.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/notifications/types -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"typename":"Recognition","typecolor":"recognition","expirymode":"dailytime","expiryhour":8,"splitperemployee":true,"showemployeephoto":true}'
|
|
```
|
|
|
|
### PUT, PATCH /api/notifications/types/<int:type_id>
|
|
|
|
**Auth:** JWT + permission `notifications.create`
|
|
**Params:** body: any of `typename` (unique-checked), `typedescription`/`description`, `typecolor`/`color`, `isactive`, `expirymode`, `expirydays`, `expiryhour`, `expiryminute`, `splitperemployee`, `showemployeephoto`, `displaystyle`
|
|
**Purpose:** Update a notification type (name/desc/color/isactive plus expiry and display fields).
|
|
|
|
```bash
|
|
curl -X PATCH http://localhost:5001/api/notifications/types/3 -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"expirymode":"duration","expirydays":14}'
|
|
```
|
|
|
|
### GET /api/notifications
|
|
|
|
**Auth:** none
|
|
**Params:** `page`, `per_page`; `active=false` to include inactive; `typeid`/`type_id`; `ticketnumber` (exact match, for idempotent import); `current=true` (within start/end window now); `search` (ILIKE on text)
|
|
**Purpose:** List notifications with filters, newest-first, paginated.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/notifications?current=true&typeid=2&search=outage&page=1'
|
|
```
|
|
|
|
### GET /api/notifications/<int:notification_id>
|
|
|
|
**Auth:** none
|
|
**Params:** path: `notification_id`
|
|
**Purpose:** Get a single notification by ID.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/notifications/42
|
|
```
|
|
|
|
### POST /api/notifications
|
|
|
|
**Auth:** JWT + permission `notifications.create`
|
|
**Params:** body: `notification`/`message` (required), `notificationtypeid`, `businessunitid`, `appid`, `starttime`/`startdate` (ISO, default now), `endtime`/`enddate` (ISO), `ticketnumber`, `link`/`linkurl`, `isshopfloor` (default false), `employeesso` (comma-list allowed), `employeename`
|
|
**Purpose:** Create a notification; `endtime` auto-derived from type expiry rule when omitted.
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5001/api/notifications -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"notification":"Line 2 press down","notificationtypeid":1,"isshopfloor":true,"ticketnumber":"INC0012345"}'
|
|
```
|
|
|
|
### PUT /api/notifications/<int:notification_id>
|
|
|
|
**Auth:** JWT + permission `notifications.edit`
|
|
**Params:** body: `notification`/`message`, `notificationtypeid`, `businessunitid`, `appid`, `ticketnumber`, `link`/`linkurl`, `isactive`, `isshopfloor`, `employeesso`, `employeename`, `starttime`/`startdate`, `endtime`/`enddate`
|
|
**Purpose:** Update any notification field; empty `starttime` resets to now, empty `endtime` clears it.
|
|
|
|
```bash
|
|
curl -X PUT http://localhost:5001/api/notifications/42 -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"endtime":"2026-08-01T12:00:00Z","isactive":true}'
|
|
```
|
|
|
|
### DELETE /api/notifications/<int:notification_id>
|
|
|
|
**Auth:** JWT + permission `notifications.delete`
|
|
**Params:** path: `notification_id`
|
|
**Purpose:** Soft-delete a notification (sets `isactive=false`, row kept).
|
|
|
|
```bash
|
|
curl -X DELETE http://localhost:5001/api/notifications/42 -H 'Authorization: Bearer $TOKEN'
|
|
```
|
|
|
|
### GET /api/notifications/active
|
|
|
|
**Auth:** none
|
|
**Params:** none
|
|
**Purpose:** Currently active notifications for display, including ones starting within a 10-day lookahead.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/notifications/active
|
|
```
|
|
|
|
### GET /api/notifications/calendar
|
|
|
|
**Auth:** none
|
|
**Params:** `start` (ISO), `end` (ISO); invalid dates silently ignored
|
|
**Purpose:** Active notifications as FullCalendar event objects for a date range.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/notifications/calendar?start=2026-07-01T00:00:00Z&end=2026-07-31T23:59:59Z'
|
|
```
|
|
|
|
### GET /api/notifications/dashboard/summary
|
|
|
|
**Auth:** none
|
|
**Params:** none
|
|
**Purpose:** Dashboard counts: total currently-active notifications plus active counts grouped by type/color.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/notifications/dashboard/summary
|
|
```
|
|
|
|
### GET /api/notifications/employee/<sso>
|
|
|
|
**Auth:** none
|
|
**Params:** path: `sso` (digits only, 400 otherwise)
|
|
**Purpose:** All active recognition-type notifications mentioning an employee SSO (exact or within comma-separated `employeesso` list).
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/notifications/employee/212345678
|
|
```
|
|
|
|
### GET /api/notifications/shopfloor
|
|
|
|
**Auth:** none
|
|
**Params:** `businessunit` (numeric BU id: returns that BU's plus null-BU notifications; omitted: null-BU only)
|
|
**Purpose:** Shopfloor TV feed: current cards (active now, or ended less than 30 min ago flagged resolved) plus upcoming (starts within 5 days); splits multi-employee cards per type config, resolves employee names/photos via employees plugin, returns `configversion` hash so kiosks reload on layout changes.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/notifications/shopfloor?businessunit=3'
|
|
```
|
|
|
|
## plugin-printedparts
|
|
|
|
### GET /api/printedparts/items
|
|
**Auth:** jwt + permission:printedparts.view
|
|
**Params:** query: page, per_page, search (matches itemcode/gagelabtag/itemname/itemdescription/binlocation), active (default true; 'false' includes retired), lowstock=true
|
|
**Purpose:** List printed items, paginated, with search and low-stock filter.
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer $TOK" 'http://localhost:5001/api/printedparts/items?search=bracket&lowstock=true&page=1&per_page=25'
|
|
```
|
|
|
|
### GET /api/printedparts/items/<int:item_id>
|
|
**Auth:** jwt + permission:printedparts.view
|
|
**Params:** path: item_id
|
|
**Purpose:** Get one printed item plus its 25 most recent ledger transactions.
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer $TOK" http://localhost:5001/api/printedparts/items/42
|
|
```
|
|
|
|
### POST /api/printedparts/items
|
|
**Auth:** jwt + permission:printedparts.create
|
|
**Params:** json body: itemname (required), gagelabtag, itemdescription, lowstockthreshold (default from printedparts_default_threshold setting, fallback 5), binlocation, printnotes; quantityonhand starts at 0
|
|
**Purpose:** Create a printed item; itemcode auto-minted from printedparts_code_prefix setting + row id; optional gagelabtag unique-checked (409 on clash).
|
|
|
|
```bash
|
|
curl -X POST -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"itemname":"Fixture clip","gagelabtag":"WJRP0042","binlocation":"B3","lowstockthreshold":10}' http://localhost:5001/api/printedparts/items
|
|
```
|
|
|
|
### PUT /api/printedparts/items/<int:item_id>
|
|
**Auth:** jwt + permission:printedparts.edit
|
|
**Params:** path: item_id; json body: any of the editable fields; gagelabtag uppercased, empty string clears it
|
|
**Purpose:** Update catalog fields (itemname, itemdescription, lowstockthreshold, binlocation, printnotes, gagelabtag); rejects quantityonhand (ledger-managed) and duplicate gagelabtag (409).
|
|
|
|
```bash
|
|
curl -X PUT -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"binlocation":"C1","lowstockthreshold":8}' http://localhost:5001/api/printedparts/items/42
|
|
```
|
|
|
|
### DELETE /api/printedparts/items/<int:item_id>
|
|
**Auth:** jwt + permission:printedparts.delete
|
|
**Params:** path: item_id
|
|
**Purpose:** Soft-retire an item (isactive=false); ledger history preserved.
|
|
|
|
```bash
|
|
curl -X DELETE -H "Authorization: Bearer $TOK" http://localhost:5001/api/printedparts/items/42
|
|
```
|
|
|
|
### POST /api/printedparts/items/<int:item_id>/restore
|
|
**Auth:** jwt + permission:printedparts.delete
|
|
**Params:** path: item_id
|
|
**Purpose:** Un-retire a soft-deleted item (isactive=true); code, photo, history intact.
|
|
|
|
```bash
|
|
curl -X POST -H "Authorization: Bearer $TOK" http://localhost:5001/api/printedparts/items/42/restore
|
|
```
|
|
|
|
### POST /api/printedparts/items/<int:item_id>/image
|
|
**Auth:** jwt + permission:printedparts.edit
|
|
**Params:** path: item_id; multipart/form-data: file=<image>
|
|
**Purpose:** Upload or replace the item's photo (png/jpg/jpeg/gif/webp); old image files for the item are deleted first, imageurl updated.
|
|
|
|
```bash
|
|
curl -X POST -H "Authorization: Bearer $TOK" -F 'file=@clip.jpg' http://localhost:5001/api/printedparts/items/42/image
|
|
```
|
|
|
|
### GET /api/printedparts/image/<path:filename>
|
|
**Auth:** none
|
|
**Params:** path: filename (e.g. printeditem-42.jpg)
|
|
**Purpose:** Serve an uploaded item image from instance/printedpartsimages (public: fetched by `<img>` tags on kiosk and lists).
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/printedparts/image/printeditem-42.jpg -o clip.jpg
|
|
```
|
|
|
|
### DELETE /api/printedparts/items/<int:item_id>/image
|
|
**Auth:** jwt + permission:printedparts.delete
|
|
**Params:** path: item_id
|
|
**Purpose:** Clear the item's imageurl; deletes the file on disk only if the URL is plugin-owned (starts with /api/printedparts/image/).
|
|
|
|
```bash
|
|
curl -X DELETE -H "Authorization: Bearer $TOK" http://localhost:5001/api/printedparts/items/42/image
|
|
```
|
|
|
|
### POST /api/printedparts/items/<int:item_id>/restock
|
|
**Auth:** jwt + permission:printedparts.restock
|
|
**Params:** path: item_id; json body: quantity (positive int, required), badge (required, 422 BadgeError if unresolvable)
|
|
**Purpose:** Add freshly printed stock via a 'restock' ledger write (single-commit ledger + cached quantity); badge resolved server-side to sso/name; 404 if item inactive.
|
|
|
|
```bash
|
|
curl -X POST -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"quantity":20,"badge":"123456789"}' http://localhost:5001/api/printedparts/items/42/restock
|
|
```
|
|
|
|
### POST /api/printedparts/items/<int:item_id>/adjust
|
|
**Auth:** jwt + permission:printedparts.restock
|
|
**Params:** path: item_id; json body: quantitychange (non-zero int, required), reason (required), badge (required)
|
|
**Purpose:** Correct the count (damage, recount) via an 'adjust' ledger write; reason mandatory; rejects driving stock below zero; fires low-stock alert on downward threshold crossing.
|
|
|
|
```bash
|
|
curl -X POST -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' -d '{"quantitychange":-3,"reason":"damaged in bin","badge":"123456789"}' http://localhost:5001/api/printedparts/items/42/adjust
|
|
```
|
|
|
|
### GET /api/printedparts/kiosk/item/<itemcode>
|
|
**Auth:** none (deliberately open per decision record; kiosk cannot carry JWT)
|
|
**Params:** path: itemcode (e.g. WJRP0042, 3DP0042, 42, or WJRP0042|3)
|
|
**Purpose:** Item summary for a scanned bin barcode; resolves full code (itemcode or gagelabtag), 'TAG|rev' QR payloads (rev stripped), or bare keypad digits when the numeric tail uniquely matches one active item.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/printedparts/kiosk/item/WJRP0042
|
|
```
|
|
|
|
### POST /api/printedparts/kiosk/take
|
|
**Auth:** none (deliberately open per decision record)
|
|
**Params:** json body: itemcode (required, same resolution as kiosk/item), badge (required, resolved server-side, 422 on BadgeError), quantity (positive int <= on hand), revision (optional int)
|
|
**Purpose:** Kiosk checkout: decrement-only 'take' ledger write, badge-attributed, bounded by quantityonhand; records optional print-file revision (explicit field or 'TAG|rev' tail); triggers low-stock alert on threshold crossing; the product's only open write.
|
|
|
|
```bash
|
|
curl -X POST -H 'Content-Type: application/json' -d '{"itemcode":"WJRP0042|3","badge":"123456789","quantity":2}' http://localhost:5001/api/printedparts/kiosk/take
|
|
```
|
|
|
|
### GET /api/printedparts/reports/stock
|
|
**Auth:** jwt-optional (like all product reports)
|
|
**Params:** query: format=csv for CSV download (printedparts-stock.csv), else JSON {columns, rows}
|
|
**Purpose:** Stock-level report for active items with low-stock flags and ledgerdelta (cache-vs-ledger reconcile; nonzero means a write bypassed the single-commit rule).
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/printedparts/reports/stock?format=csv' -o stock.csv
|
|
```
|
|
|
|
### GET /api/printedparts/reports/consumption
|
|
**Auth:** jwt-optional
|
|
**Params:** query: days (default 30; 0 or negative = all time), format=csv (printedparts-consumption.csv)
|
|
**Purpose:** Take-transactions aggregated per item (takes count + quantitytaken), sorted by quantity taken descending.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/printedparts/reports/consumption?days=90'
|
|
```
|
|
|
|
### GET /api/printedparts/reports/by-person
|
|
**Auth:** jwt-optional
|
|
**Params:** query: days (default 30; 0 or negative = all time), format=csv (printedparts-by-person.csv)
|
|
**Purpose:** Take-transactions grouped by employee SSO (takes count + quantitytaken), sorted by quantity taken descending.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/printedparts/reports/by-person?days=30&format=csv' -o by-person.csv
|
|
```
|
|
|
|
### GET /api/printedparts/items/<int:item_id>/files
|
|
**Auth:** jwt + permission:printedparts.view
|
|
**Params:** path: item_id
|
|
**Purpose:** List the item's print-file revision history, newest revision first.
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer $TOK" http://localhost:5001/api/printedparts/items/42/files
|
|
```
|
|
|
|
### POST /api/printedparts/items/<int:item_id>/files
|
|
**Auth:** jwt + permission:printedparts.edit
|
|
**Params:** path: item_id; multipart/form-data: file=<print file> (required), note=<what changed> (optional)
|
|
**Purpose:** Upload the next print-file revision (append-only, auto-numbered max+1); allowed ext: stl/3mf/gcode/gco/bgcode/step/stp/obj/amf; 100 MB cap; uploader recorded from JWT identity.
|
|
|
|
```bash
|
|
curl -X POST -H "Authorization: Bearer $TOK" -F 'file=@clip-v2.stl' -F 'note=thicker wall' http://localhost:5001/api/printedparts/items/42/files
|
|
```
|
|
|
|
### GET /api/printedparts/files/<int:file_id>/download
|
|
**Auth:** jwt-optional
|
|
**Params:** path: file_id
|
|
**Purpose:** Download a print-file revision as an attachment under its original filename (jwt-optional so plain anchor downloads work).
|
|
|
|
```bash
|
|
curl -OJ http://localhost:5001/api/printedparts/files/7/download
|
|
```
|
|
|
|
### DELETE /api/printedparts/files/<int:file_id>
|
|
**Auth:** jwt + permission:printedparts.delete
|
|
**Params:** path: file_id
|
|
**Purpose:** Delete a bad print-file revision (wrong file uploaded): removes the stored file and the DB record.
|
|
|
|
```bash
|
|
curl -X DELETE -H "Authorization: Bearer $TOK" http://localhost:5001/api/printedparts/files/7
|
|
```
|
|
|
|
## plugin-printers
|
|
|
|
### GET /api/printers/types
|
|
**Auth:** jwt-optional
|
|
**Params:** page, per_page, active (default true; 'false' includes inactive), search
|
|
**Purpose:** List printer types, paginated, with active filter and name search.
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer $TOKEN" 'http://localhost:5001/api/printers/types?search=laser&active=false'
|
|
```
|
|
|
|
### GET /api/printers/types/<type_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** path: type_id (int)
|
|
**Purpose:** Get a single printer type by ID.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/printers/types/3
|
|
```
|
|
|
|
### POST /api/printers/types
|
|
**Auth:** permission:printers.create
|
|
**Params:** body: printertype (required), description, icon, color; reactivates a matching inactive type instead of 409
|
|
**Purpose:** Create a new printer type (or reactivate an inactive duplicate).
|
|
|
|
```bash
|
|
curl -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"printertype":"Label","color":"#00f"}' http://localhost:5001/api/printers/types
|
|
```
|
|
|
|
### PUT /api/printers/types/<type_id>
|
|
**Auth:** permission:printers.edit
|
|
**Params:** body: printertype, description, icon, color, isactive (any subset); 409 on name clash
|
|
**Purpose:** Update a printer type.
|
|
|
|
```bash
|
|
curl -X PUT -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"isactive":false}' http://localhost:5001/api/printers/types/3
|
|
```
|
|
|
|
### DELETE /api/printers/types/<type_id>
|
|
**Auth:** permission:printers.delete
|
|
**Params:** path: type_id; 409 if any printer still references the type
|
|
**Purpose:** Hard-delete a printer type when unused.
|
|
|
|
```bash
|
|
curl -X DELETE -H "Authorization: Bearer $TOKEN" http://localhost:5001/api/printers/types/3
|
|
```
|
|
|
|
### GET /api/printers/drivers
|
|
**Auth:** jwt-optional
|
|
**Params:** active (default true; 'false' includes inactive). Unpaginated.
|
|
**Purpose:** List printer driver packages (named SMB/HTTP links).
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/printers/drivers?active=false'
|
|
```
|
|
|
|
### POST /api/printers/drivers
|
|
**Auth:** permission:printers.create
|
|
**Params:** body: name (required), location (required), description, modelnumberid, isactive
|
|
**Purpose:** Create a driver entry.
|
|
|
|
```bash
|
|
curl -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"name":"HP UPD","location":"\\\\fileserver\\drivers\\hpupd"}' http://localhost:5001/api/printers/drivers
|
|
```
|
|
|
|
### PUT /api/printers/drivers/<driver_id>
|
|
**Auth:** permission:printers.edit
|
|
**Params:** body: name, location, description, isactive, modelnumberid (any subset)
|
|
**Purpose:** Update a driver entry.
|
|
|
|
```bash
|
|
curl -X PUT -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"isactive":false}' http://localhost:5001/api/printers/drivers/5
|
|
```
|
|
|
|
### DELETE /api/printers/drivers/<driver_id>
|
|
**Auth:** permission:printers.delete
|
|
**Params:** path: driver_id
|
|
**Purpose:** Hard-delete a driver entry.
|
|
|
|
```bash
|
|
curl -X DELETE -H "Authorization: Bearer $TOKEN" http://localhost:5001/api/printers/drivers/5
|
|
```
|
|
|
|
### GET /api/printers
|
|
**Auth:** jwt-optional
|
|
**Params:** page, per_page, active, assetnumber (exact-match for import idempotency), search (assetnumber/name/serial/hostname/windowsname), typeid|type_id, vendorid|vendor_id, locationid|location_id, businessunitid|businessunit_id, sort (hostname|assetnumber|name), dir (asc|desc)
|
|
**Purpose:** List printers (joined Asset+Printer) with filters, search, sorting, pagination; each row includes primary IP.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/printers?search=csf&typeid=2&sort=assetnumber&dir=desc'
|
|
```
|
|
|
|
### GET /api/printers/install-list
|
|
**Auth:** jwt-optional
|
|
**Params:** format=text for pipe-delimited installer variant (printerid|windowsname|vendorname|modelnumber|hostname|ipaddress|mapx|mapy); default JSON
|
|
**Purpose:** Flat unpaginated list of active network printers (with map positions) for the signed printer-installer EXE; replaces classic apiprinters.asp.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/printers/install-list?format=text'
|
|
```
|
|
|
|
### GET /api/printers/install-batch
|
|
**Auth:** jwt-optional
|
|
**Params:** printerids (required, comma-separated printer IDs)
|
|
**Purpose:** Generate and download a Windows .bat that installs selected printers (HP/Xerox via universal PrinterInstaller.exe, per-printer .exe /SILENT, or flags manual).
|
|
|
|
```bash
|
|
curl -OJ 'http://localhost:5001/api/printers/install-batch?printerids=1,2,3'
|
|
```
|
|
|
|
### GET /api/printers/pc-default
|
|
**Auth:** jwt-optional
|
|
**Params:** machine (PC asset number), format=text for pipe-delimited variant; returns {} / empty body if no default set
|
|
**Purpose:** Look up a PC's default printer via the defaultprinter asset relationship (parity with classic apipcdefaultprinter.asp); used by installer to preselect map hotspot.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/printers/pc-default?machine=0421&format=text'
|
|
```
|
|
|
|
### GET /api/printers/<printer_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** path: printer_id (int)
|
|
**Purpose:** Get one printer with full asset details, communications, and active drivers matching its model.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/printers/17
|
|
```
|
|
|
|
### GET /api/printers/by-asset/<asset_id>
|
|
**Auth:** jwt-optional
|
|
**Params:** path: asset_id (int)
|
|
**Purpose:** Get printer data keyed by core asset ID.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/printers/by-asset/204
|
|
```
|
|
|
|
### POST /api/printers
|
|
**Auth:** permission:printers.create
|
|
**Params:** body: assetnumber (required); name, serialnumber, gaugelabreference, maintenancereference, statusid, locationid, businessunitid, printertypeid, vendorid, modelnumberid, hostname, windowsname, sharename, iscsf, installpath, pin, iscolor, isduplex, isnetwork, mapx, mapy, notes, ipaddress (creates primary IP comm); X-Import-Mode header preserves legacy timestamps
|
|
**Purpose:** Create a printer (Asset + Printer extension + optional primary IP communication).
|
|
|
|
```bash
|
|
curl -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"assetnumber":"PR-0042","hostname":"wjprn042","ipaddress":"10.1.2.42","printertypeid":1}' http://localhost:5001/api/printers
|
|
```
|
|
|
|
### PUT /api/printers/<printer_id>
|
|
**Auth:** permission:printers.edit
|
|
**Params:** body: any subset of asset fields (assetnumber, name, serialnumber, gaugelabreference, maintenancereference, statusid, locationid, businessunitid, mapx, mapy, notes, isactive) + printer fields (printertypeid, vendorid, modelnumberid, hostname, windowsname, sharename, iscsf, installpath, pin, iscolor, isduplex, isnetwork) + ipaddress (upserts/clears primary IP comm); 409 on assetnumber clash
|
|
**Purpose:** Update printer: asset, extension, and primary IP in one call.
|
|
|
|
```bash
|
|
curl -X PUT -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"ipaddress":"10.1.2.99","iscolor":true}' http://localhost:5001/api/printers/17
|
|
```
|
|
|
|
### DELETE /api/printers/<printer_id>
|
|
**Auth:** permission:printers.delete
|
|
**Params:** path: printer_id
|
|
**Purpose:** Soft-delete a printer (sets the underlying asset isactive=false).
|
|
|
|
```bash
|
|
curl -X DELETE -H "Authorization: Bearer $TOKEN" http://localhost:5001/api/printers/17
|
|
```
|
|
|
|
### GET /api/printers/<printer_id>/supplies
|
|
**Auth:** jwt-optional
|
|
**Params:** path: printer_id; needs an IP communication on the printer
|
|
**Purpose:** Real-time supply levels from Zabbix for one printer, annotated with status/color/part numbers; fails soft (empty supplies, pingstatus -1) when Zabbix is off/unreachable.
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer $TOKEN" http://localhost:5001/api/printers/17/supplies
|
|
```
|
|
|
|
### GET /api/printers/lowsupplies
|
|
**Auth:** jwt-optional
|
|
**Params:** none (data cached 5 min)
|
|
**Purpose:** Fleet-wide report of printers with low/critical supply levels from Zabbix, with summary counts.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/printers/lowsupplies
|
|
```
|
|
|
|
### GET /api/printers/lookup
|
|
**Auth:** jwt-optional
|
|
**Params:** ip or fqdn (one required; value matched against communication ipaddress)
|
|
**Purpose:** Find a printer by IP/FQDN (parity with classic printerlookup.asp; used by Zabbix to deep-link to a printer record).
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/printers/lookup?ip=10.1.2.42'
|
|
```
|
|
|
|
### POST /api/printers/supplies/refresh
|
|
**Auth:** permission:printers.create
|
|
**Params:** none
|
|
**Purpose:** Clear the cached Zabbix supply data so next reads pull fresh values (toner-report Refresh button).
|
|
|
|
```bash
|
|
curl -X POST -H "Authorization: Bearer $TOKEN" http://localhost:5001/api/printers/supplies/refresh
|
|
```
|
|
|
|
### GET /api/printers/dashboard/summary
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** Dashboard summary: total active printers, counts by type and vendor, low/critical supply counts (Zabbix, if reachable).
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/printers/dashboard/summary
|
|
```
|
|
|
|
### GET /api/printers/supplies/meta
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** Allowed enum values for supplytype, color, and capacitytier (for the UI forms).
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/printers/supplies/meta
|
|
```
|
|
|
|
### GET /api/printers/models
|
|
**Auth:** jwt-optional
|
|
**Params:** page, per_page, search (modelnumber), vendorid|vendor_id, withsupplies=true (only models that already have supplies)
|
|
**Purpose:** List printer models with supply counts for the supply-management picker (restricted to models attached to printers or already carrying supplies).
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/printers/models?withsupplies=true&search=M404'
|
|
```
|
|
|
|
### GET /api/printers/models/<modelnumberid>/supplies
|
|
**Auth:** jwt-optional
|
|
**Params:** path: modelnumberid (int)
|
|
**Purpose:** List all active supplies (toner/drum/waste part numbers) mapped to a model.
|
|
|
|
```bash
|
|
curl http://localhost:5001/api/printers/models/12/supplies
|
|
```
|
|
|
|
### POST /api/printers/models/<modelnumberid>/supplies
|
|
**Auth:** permission:printers.create
|
|
**Params:** body: partnumber (required), supplytype (default toner), color (default none), capacitytier (default standard), marketingname, pageyield, notes; 409 if part already mapped to model
|
|
**Purpose:** Add a supply part-number mapping to a model.
|
|
|
|
```bash
|
|
curl -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"partnumber":"CF259A","supplytype":"toner","color":"black"}' http://localhost:5001/api/printers/models/12/supplies
|
|
```
|
|
|
|
### PUT /api/printers/supplies/<modelsupplyid>
|
|
**Auth:** permission:printers.edit
|
|
**Params:** body: any subset of supplytype, color, capacitytier, partnumber, marketingname, pageyield, notes; enum-validated, 409 on partnumber clash within model
|
|
**Purpose:** Update a model supply mapping.
|
|
|
|
```bash
|
|
curl -X PUT -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"capacitytier":"high"}' http://localhost:5001/api/printers/supplies/44
|
|
```
|
|
|
|
### DELETE /api/printers/supplies/<modelsupplyid>
|
|
**Auth:** permission:printers.delete
|
|
**Params:** path: modelsupplyid
|
|
**Purpose:** Hard-delete a model supply mapping.
|
|
|
|
```bash
|
|
curl -X DELETE -H "Authorization: Bearer $TOKEN" http://localhost:5001/api/printers/supplies/44
|
|
```
|
|
|
|
## plugin-slides
|
|
|
|
### GET /api/slides/feed
|
|
**Auth:** none
|
|
**Params:** query: `surface=lobby|shopfloor` (default `lobby`; invalid values fall back to `lobby`). Returns `{success, surface, basepath, interval, slides:[{filename, seconds}]}`; only slides whose file exists on disk are listed.
|
|
**Purpose:** Public flat playlist for a surface (lobby/shopfloor). Raw `jsonify`, not the `success_response` envelope, so the screensaver parser works unchanged.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/slides/feed?surface=shopfloor'
|
|
```
|
|
|
|
### GET /api/slides/img/<surface>/<path:filename>
|
|
**Auth:** none
|
|
**Params:** path: `surface` (`lobby|shopfloor`), `filename` (must equal its basename).
|
|
**Purpose:** Public serving of a single slide image from `instance/slides/<surface>/`, with basename path-traversal guard. 404 on unknown surface, traversal attempt, or missing file.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/slides/img/lobby/Slide1.png' -o Slide1.png
|
|
```
|
|
|
|
### GET /api/slides/<surface>
|
|
**Auth:** jwt + permission:slides.manage
|
|
**Params:** path: `surface` (`lobby|shopfloor`; else `VALIDATION_ERROR`).
|
|
**Purpose:** Admin list of a surface's slides (TvSlide rows ordered by `sortorder, slideid`, filtered to files present on disk), each with a `url` field for the img route.
|
|
|
|
```bash
|
|
curl -H 'Authorization: Bearer $TOKEN' 'http://localhost:5001/api/slides/lobby'
|
|
```
|
|
|
|
### POST /api/slides/<surface>/upload
|
|
**Auth:** jwt + permission:slides.manage
|
|
**Params:** path: `surface`. multipart/form-data body: `files` (repeatable) or single `file`. Allowed extensions: `.jpg .jpeg .png .gif .bmp .webp`. Returns `{added:[names]}`.
|
|
**Purpose:** Upload one or more slide images. Non-image extensions skipped, names `secure_filename`'d and unique-renamed (`stem_N.ext`) on collision, appended after current max sortorder in natural filename order, `seconds=0` (surface default).
|
|
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $TOKEN' -F 'files=@Slide1.png' -F 'files=@Slide2.png' 'http://localhost:5001/api/slides/lobby/upload'
|
|
```
|
|
|
|
### POST /api/slides/<surface>/order
|
|
**Auth:** jwt + permission:slides.manage
|
|
**Params:** path: `surface`. JSON body: `{order: [filename, ...]}`.
|
|
**Purpose:** Save play order: each filename in the `order` array gets `sortorder` set to its index; unknown filenames silently ignored.
|
|
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"order":["Slide2.png","Slide1.png"]}' 'http://localhost:5001/api/slides/lobby/order'
|
|
```
|
|
|
|
### POST /api/slides/<surface>/delete
|
|
**Auth:** jwt + permission:slides.manage
|
|
**Params:** path: `surface`. JSON body: `{files: [filename, ...]}`.
|
|
**Purpose:** Delete named slides: removes file from disk (OSError swallowed) and the TvSlide row. Filenames reduced to basename first; returns count of DB rows removed.
|
|
|
|
```bash
|
|
curl -X POST -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"files":["Slide1.png"]}' 'http://localhost:5001/api/slides/shopfloor/delete'
|
|
```
|
|
|
|
### PATCH /api/slides/<surface>/<int:slideid>
|
|
**Auth:** jwt + permission:slides.manage
|
|
**Params:** path: `surface`, `slideid` (int). JSON body: `{seconds: int}` (non-int -> `VALIDATION_ERROR`).
|
|
**Purpose:** Update a single slide's per-slide duration. `seconds` clamped to `>=0` (`0` means use the 10s surface default); 404 if slide missing or belongs to a different surface.
|
|
|
|
```bash
|
|
curl -X PATCH -H 'Authorization: Bearer $TOKEN' -H 'Content-Type: application/json' -d '{"seconds":15}' 'http://localhost:5001/api/slides/lobby/12'
|
|
```
|
|
|
|
## plugin-usb
|
|
|
|
USB device inventory with check-in/check-out tracking. Dual-mode backend: self-hosted tables or external `cmmc_usb` DB, selected by the `usb_directory_mode` setting.
|
|
|
|
### GET /api/usb
|
|
|
|
**Auth:** JWT optional
|
|
**Params:** query: `page`, `per_page`, `status` (`available` | `checkedout` | `retired`), `search` (matches `device_id` or `device_desc`)
|
|
**Purpose:** List USB devices with checkout status (paginated).
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/usb?status=available&search=kingston&page=1&per_page=25' -H 'Authorization: Bearer $JWT'
|
|
```
|
|
|
|
### GET /api/usb/<device_id>
|
|
|
|
**Auth:** JWT optional
|
|
**Params:** path: `device_id`
|
|
**Purpose:** Get one device plus its last 20 check-in/out log rows. 404 if unknown.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/usb/USB-0042' -H 'Authorization: Bearer $JWT'
|
|
```
|
|
|
|
### POST /api/usb
|
|
|
|
**Auth:** JWT + permission `usb.create`
|
|
**Params:** body JSON: `device_id` (required), `device_desc`, `device_owner` (badge), `locker_location`
|
|
**Purpose:** Create a device; starts in checked-in status. 409 on duplicate `device_id`.
|
|
|
|
```bash
|
|
curl -X POST 'http://localhost:5001/api/usb' -H 'Authorization: Bearer $JWT' -H 'Content-Type: application/json' -d '{"device_id":"USB-0042","device_desc":"Kingston 32GB","device_owner":"212345678","locker_location":"A3"}'
|
|
```
|
|
|
|
### PUT /api/usb/<device_id>
|
|
|
|
**Auth:** JWT + permission `usb.edit`
|
|
**Params:** path: `device_id`; body JSON: any of `device_desc`, `device_owner`, `locker_location`, `status`
|
|
**Purpose:** Edit device fields. 404 if unknown.
|
|
|
|
```bash
|
|
curl -X PUT 'http://localhost:5001/api/usb/USB-0042' -H 'Authorization: Bearer $JWT' -H 'Content-Type: application/json' -d '{"device_desc":"Kingston 64GB","locker_location":"B1"}'
|
|
```
|
|
|
|
### POST /api/usb/<device_id>/retire
|
|
|
|
**Auth:** JWT + permission `usb.edit`
|
|
**Params:** path: `device_id`; no body
|
|
**Purpose:** Retire a device (sets status to `retired`). 404 if unknown.
|
|
|
|
```bash
|
|
curl -X POST 'http://localhost:5001/api/usb/USB-0042/retire' -H 'Authorization: Bearer $JWT'
|
|
```
|
|
|
|
### POST /api/usb/<device_id>/checkout
|
|
|
|
**Auth:** JWT + permission `usb.create`
|
|
**Params:** path: `device_id`; body JSON: `badge` (required), `locker_location` (optional, also updates the device)
|
|
**Purpose:** Check a device out to a badge. Writes a check-out log row, sets status to checked-out, auto-creates the user from the HR directory. 409 if already checked out.
|
|
|
|
```bash
|
|
curl -X POST 'http://localhost:5001/api/usb/USB-0042/checkout' -H 'Authorization: Bearer $JWT' -H 'Content-Type: application/json' -d '{"badge":"212345678","locker_location":"A3"}'
|
|
```
|
|
|
|
### POST /api/usb/<device_id>/checkin
|
|
|
|
**Auth:** JWT + permission `usb.create`
|
|
**Params:** path: `device_id`; body JSON: `badge` (required), `locker_location`, `sanitized` (bool/1/0), `scanned_viruses` (bool/1/0)
|
|
**Purpose:** Check a device back in. Writes a check-in log row with sanitized/virus-scan flags, sets status to checked-in. 400 if not currently checked out.
|
|
|
|
```bash
|
|
curl -X POST 'http://localhost:5001/api/usb/USB-0042/checkin' -H 'Authorization: Bearer $JWT' -H 'Content-Type: application/json' -d '{"badge":"212345678","sanitized":true,"scanned_viruses":true}'
|
|
```
|
|
|
|
### GET /api/usb/<device_id>/history
|
|
|
|
**Auth:** JWT optional
|
|
**Params:** path: `device_id`; query: `page`, `per_page`
|
|
**Purpose:** Paginated check-in/out log for one device, newest first.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/usb/USB-0042/history?page=1&per_page=50' -H 'Authorization: Bearer $JWT'
|
|
```
|
|
|
|
### GET /api/usb/checkouts
|
|
|
|
**Auth:** JWT optional
|
|
**Params:** query: `page`, `per_page`, `active=true` (only rows whose device is still checked out), `badge` (filter by `badge_number`)
|
|
**Purpose:** List check-out log rows (paginated), each with the device's current status joined in.
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/usb/checkouts?active=true&badge=212345678' -H 'Authorization: Bearer $JWT'
|
|
```
|
|
|
|
### GET /api/usb/checkouts/active
|
|
|
|
**Auth:** JWT optional
|
|
**Params:** query: `badge` (filter by `badge_number`)
|
|
**Purpose:** Latest check-out log row for every currently checked-out device (non-paginated list).
|
|
|
|
```bash
|
|
curl 'http://localhost:5001/api/usb/checkouts/active?badge=212345678' -H 'Authorization: Bearer $JWT'
|
|
```
|
|
|
|
## plugin-warranty
|
|
|
|
### GET /api/warranty
|
|
|
|
**Auth:** jwt-optional
|
|
**Params:** query: `active` (default true; 'false' includes inactive), `servicetag` (exact match, for idempotent import), `vendor` (exact match), `assetid` (int, filter to warranties covering that asset), `status` (post-filter on derived status: `expired|expiring|active|unknown`)
|
|
**Purpose:** List warranties with linked-asset summaries and derived status (batch asset fetch, ordered by enddate with null last).
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer $TOKEN" 'http://localhost:5001/api/warranty?status=expiring&assetid=42'
|
|
```
|
|
|
|
### GET /api/warranty/asset/<int:assetid>
|
|
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `assetid`
|
|
**Purpose:** Active warranties covering one asset, for the asset-detail panel.
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer $TOKEN" http://localhost:5001/api/warranty/asset/42
|
|
```
|
|
|
|
### GET /api/warranty/<int:warrantyid>
|
|
|
|
**Auth:** jwt-optional
|
|
**Params:** path: `warrantyid`
|
|
**Purpose:** Fetch a single warranty by id with asset summaries; 404 if missing.
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer $TOKEN" http://localhost:5001/api/warranty/7
|
|
```
|
|
|
|
### POST /api/warranty
|
|
|
|
**Auth:** jwt + permission: `warranty.create`
|
|
**Params:** JSON body: `vendor` (required), `servicetag`, `provider` (default 'manual', lowercased), `servicelevel`, `startdate` (YYYY-MM-DD), `enddate` (YYYY-MM-DD), `notes`, `assetids` (list of asset ids to link)
|
|
**Purpose:** Create a warranty (vendor required) and optionally link it to assets; returns 201.
|
|
|
|
```bash
|
|
curl -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"vendor":"Dell","servicetag":"ABC1234","enddate":"2027-06-30","assetids":[42]}' http://localhost:5001/api/warranty
|
|
```
|
|
|
|
### PUT /api/warranty/<int:warrantyid>
|
|
|
|
**Auth:** jwt + permission: `warranty.edit`
|
|
**Params:** path: `warrantyid`; JSON body (all optional): `vendor`, `servicetag`, `provider`, `servicelevel`, `startdate`, `enddate`, `notes`, `isactive` (bool), `assetids` (full replacement list)
|
|
**Purpose:** Partial update of any warranty field (only keys present in body change), including isactive and replacing asset links via assetids.
|
|
|
|
```bash
|
|
curl -X PUT -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"enddate":"2028-01-15","assetids":[42,43]}' http://localhost:5001/api/warranty/7
|
|
```
|
|
|
|
### DELETE /api/warranty/<int:warrantyid>
|
|
|
|
**Auth:** jwt + permission: `warranty.delete`
|
|
**Params:** path: `warrantyid`
|
|
**Purpose:** Hard-delete a warranty (and its asset links); 404 if missing.
|
|
|
|
```bash
|
|
curl -X DELETE -H "Authorization: Bearer $TOKEN" http://localhost:5001/api/warranty/7
|
|
```
|
|
|
|
### POST /api/warranty/<int:warrantyid>/refresh
|
|
|
|
**Auth:** jwt + permission: `warranty.edit`
|
|
**Params:** path: `warrantyid`; no body
|
|
**Purpose:** Re-query the warranty's provider (dell etc.) by service tag and update servicelevel/startdate/enddate + lastcheckeddate; 400 if provider is manual or not configured.
|
|
|
|
```bash
|
|
curl -X POST -H "Authorization: Bearer $TOKEN" http://localhost:5001/api/warranty/7/refresh
|
|
```
|
|
|
|
### POST /api/warranty/sync/dell
|
|
|
|
**Auth:** jwt + permission: `warranty.edit`
|
|
**Params:** query: `all` (default false; 'true' re-checks assets that already have a dated warranty); no body
|
|
**Purpose:** Bulk Dell sync: look up serials of active assets lacking a dated warranty via Dell bulk_lookup, creating or updating (canonicalizing to provider dell) warranties; returns candidates/tags/matched/created/updated counts.
|
|
|
|
```bash
|
|
curl -X POST -H "Authorization: Bearer $TOKEN" 'http://localhost:5001/api/warranty/sync/dell?all=true'
|
|
```
|
|
|
|
### GET /api/warranty/report
|
|
|
|
**Auth:** jwt-optional
|
|
**Params:** none
|
|
**Purpose:** Report for the Reports hub: active warranties bucketed by derived status (expired/expiring/active/unknown) with per-bucket counts and full lists.
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer $TOKEN" http://localhost:5001/api/warranty/report
|
|
```
|