-
Notifications
You must be signed in to change notification settings - Fork 0
API Assets
title: "API — Assets" category: "api" version: "1.0" last_updated: "2024-01-15" standards: ["NIST-SP-800-53", "ISA-IEC-62443"] related_pages: ["API-Overview", "API-Credentials", "API-Maintenance", "Database-Assets-DB", "Workflow-Rotation-Task", "Security-Authorization-Model"] ai_summary: "VaultFlower Assets API endpoints. Full hierarchy: Locations, Systems, Zones, Assets. CRUD operations for each level. Criticality level changes require justification and generate CRITICAL SIEM events. Asset status updates (online/offline) trigger rotation scheduling. Shortcut GET /assets/{id} available without full hierarchy path."
https://vfw-core.contoso.com/api/v1/{tenant-slug}/
Asset hierarchy follows ISA/IEC 62443 Zones and Conduits model:
/locations
/locations/{id}/systems
/locations/{id}/systems/{id}/zones
/locations/{id}/systems/{id}/zones/{id}/assets
/assets/{id} ← shortcut (no hierarchy path needed)
Create a new location. Admin only.
POST /api/v1/acme-corp/locations
Authorization: Bearer {admin_token}
Content-Type: application/json
X-Request-ID: {uuid}{
"name": "North-Site",
"code": "PLT-NORTH",
"country": "Country",
"region": "Западная Сибирь",
"city": "City",
"address": "st. Address, h-no",
"latitude": 60.9344,
"longitude": 76.5531,
"timezone": "Asia/Moon"
}Response 201:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "North-Site",
"code": "PLT-NORTH",
"timezone": "Asia/Moon",
"is_active": true,
"created_at": "2024-01-15T08:00:00Z"
}Errors: 409 CODE_EXISTS — location code already in use for this tenant.
SIEM: location.created (INFO)
List all locations for the tenant.
GET /api/v1/acme-corp/locations?is_active=true&page=1&page_size=20
Authorization: Bearer {access_token}
X-Request-ID: {uuid}Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
is_active |
boolean | true | Filter by active status |
page |
integer | 1 | Page number |
page_size |
integer | 20 | Items per page (max 100) |
Response 200:
{
"items": [
{
"id": "a1b2c3d4-...",
"name": "North-Site",
"code": "PLT-NORTH",
"country": "Country",
"city": "City",
"timezone": "Asia/Moon",
"is_active": true,
"systems_count": 3,
"assets_count": 24
}
],
"total": 2,
"page": 1,
"page_size": 20,
"total_pages": 1
}Access: All roles (scope-filtered for non-Admin)
Get location details.
GET /api/v1/acme-corp/locations/a1b2c3d4-e5f6-7890-abcd-ef1234567890
Authorization: Bearer {access_token}
X-Request-ID: {uuid}Response 200:
{
"id": "a1b2c3d4-...",
"name": "North-Site",
"code": "PLT-NORTH",
"country": "Country",
"region": "Западная Сибирь",
"city": "City",
"address": "st. Address, h-no",
"latitude": 60.9344,
"longitude": 76.5531,
"timezone": "Asia/Moon",
"is_active": true,
"created_at": "2024-01-15T08:00:00Z",
"created_by": "admin@contoso.com",
"systems_count": 3,
"assets_count": 24
}Update location. Admin only. Only provided fields are updated.
PATCH /api/v1/acme-corp/locations/a1b2c3d4-e5f6-7890-abcd-ef1234567890
Authorization: Bearer {admin_token}
Content-Type: application/json
X-Request-ID: {uuid}{
"address": "st. Address, ho-no-2",
"city": "City"
}Response 200: Updated location object.
SIEM: location.updated (INFO)
Deactivate location. Admin only. Soft delete — sets is_active = false.
DELETE /api/v1/acme-corp/locations/a1b2c3d4-e5f6-7890-abcd-ef1234567890
Authorization: Bearer {admin_token}
X-Request-ID: {uuid}Response 204: Location deactivated.
Response 409: HAS_ACTIVE_SYSTEMS — location has active systems. Deactivate systems first.
SIEM: location.deactivated (WARN)
Create a system within a location. Admin only.
POST /api/v1/acme-corp/locations/a1b2c3d4-.../systems
Authorization: Bearer {admin_token}
Content-Type: application/json
X-Request-ID: {uuid}{
"name": "SCADA-Production",
"code": "SCADA-OIL-01",
"system_type": "SCADA",
"description": "Oil production management system",
"criticality_level": "CRITICAL",
"criticality_type": "COMBINED",
"criticality_justification": "Controls oil production. Failure causes economic loss and environmental risk.",
"owner_name": "John, Doe sr.",
"owner_title": "Главный инженер",
"owner_email": "j.doe.sr@company.ru",
"owner_phone": "+7-999-123-45-67",
"deputy_name": "Петров Александр Иванович",
"deputy_email": "petrov.a@company.ru",
"working_hours_start": "08:00",
"working_hours_end": "20:00",
"working_days": "1,2,3,4,5"
}Response 201:
{
"id": "b2c3d4e5-f6a7-8901-bcde-f01234567890",
"name": "SCADA-Production",
"code": "SCADA-OIL-01",
"system_type": "SCADA",
"criticality_level": "CRITICAL",
"is_active": true,
"created_at": "2024-01-15T08:00:00Z"
}SIEM: system.created (INFO)
List systems in a location.
GET /api/v1/acme-corp/locations/a1b2c3d4-.../systems
Authorization: Bearer {access_token}
X-Request-ID: {uuid}Response 200:
{
"items": [
{
"id": "b2c3d4e5-...",
"name": "SCADA-Production",
"code": "SCADA-OIL-01",
"system_type": "SCADA",
"criticality_level": "CRITICAL",
"criticality_type": "COMBINED",
"owner_name": "John, Doe sr.",
"owner_email": "j.doe.sr@company.ru",
"is_active": true,
"zones_count": 4,
"assets_count": 12
}
],
"total": 3,
"page": 1,
"page_size": 20,
"total_pages": 1
}Get system details.
Response 200: Full system object including all owner fields and working hours.
Update system. Admin only.
Special rule for criticality_level change:
{
"criticality_level": "HIGH",
"criticality_change_reason": "Risk reassessment per annual audit — downgraded from CRITICAL to HIGH"
}criticality_change_reason is required when changing criticality_level. Missing reason → 400 REASON_REQUIRED.
SIEM:
-
system.updated(INFO) — general update -
system.criticality_changed(CRITICAL) — criticality level changed
Deactivate system. Admin only.
Response 409: HAS_ACTIVE_ZONES or HAS_ACTIVE_CHECKOUTS
SIEM: system.deactivated (WARN)
Create a zone. Admin only.
POST /api/v1/acme-corp/locations/a1b2c3d4-.../systems/b2c3d4e5-.../zones
Authorization: Bearer {admin_token}
Content-Type: application/json
X-Request-ID: {uuid}{
"name": "OT-DMZ-North",
"code": "OT-DMZ-NORTH",
"zone_type": "DMZ",
"network_type": "OT_DOMAIN",
"domain_name": "ot.contoso.com",
"ip_range": "10.10.1.0/24",
"is_air_gapped": false,
"description": "IT/OT demilitarized zone — North plant"
}Response 201:
{
"id": "c3d4e5f6-a7b8-9012-cdef-012345678901",
"name": "OT-DMZ-North",
"code": "OT-DMZ-NORTH",
"zone_type": "DMZ",
"network_type": "OT_DOMAIN",
"is_air_gapped": false,
"is_active": true,
"created_at": "2024-01-15T08:00:00Z"
}SIEM: zone.created (INFO)
List zones in a system.
Response 200:
{
"items": [
{
"id": "c3d4e5f6-...",
"name": "OT-DMZ-North",
"code": "OT-DMZ-NORTH",
"zone_type": "DMZ",
"network_type": "OT_DOMAIN",
"domain_name": "ot.contoso.com",
"ip_range": "10.10.1.0/24",
"is_air_gapped": false,
"is_active": true,
"assets_count": 5
}
],
"total": 4,
"page": 1,
"page_size": 20,
"total_pages": 1
}Get zone details.
Response 200: Full zone object.
Update zone. Admin only.
SIEM: zone.updated (INFO)
Deactivate zone. Admin only.
Response 409: HAS_ACTIVE_ASSETS or HAS_ACTIVE_CHECKOUTS
SIEM: zone.deactivated (WARN)
Create an asset. Admin only.
POST /api/v1/acme-corp/locations/a1b2c3d4-.../systems/b2c3d4e5-.../zones/c3d4e5f6-.../assets
Authorization: Bearer {admin_token}
Content-Type: application/json
X-Request-ID: {uuid}{
"name": "System1",
"code": "SRV-OT-001",
"asset_type": "SERVER",
"hostname": "system1",
### GET /locations/{location-id}/systems/{system-id}/zones/{zone-id}/assets/{asset-id}
Get full asset details.
```http
GET /api/v1/acme-corp/locations/a1b2c3d4-.../systems/b2c3d4e5-.../zones/c3d4e5f6-.../assets/d4e5f6a7-...
Authorization: Bearer {access_token}
X-Request-ID: {uuid}Response 200:
{
"id": "d4e5f6a7-b8c9-0123-defa-123456789012",
"name": "System1",
"code": "SRV-OT-001",
"asset_type": "SERVER",
"hostname": "system1",
"fqdn": "system1.ot.contoso.com",
"ip_address": "10.10.1.101",
"mac_address": "00:1A:2B:3C:4D:5E",
"os_type": "WINDOWS",
"os_name": "Windows Server 2019",
"os_version": "10.0.17763",
"is_domain_joined": true,
"domain_name": "ot.contoso.com",
"is_online": false,
"last_seen_at": "2024-01-10T15:00:00Z",
"rotation_method": "SCHEDULED_MANUAL",
"rotation_port": null,
"serial_number": "SN-12345-XYZ",
"specification": {
"cpu": "Intel Xeon E5-2680",
"ram_gb": 32,
"storage": "2x 500GB SSD RAID1"
},
"description": "Primary SCADA server for oil production control",
"zone": {
"id": "c3d4e5f6-...",
"name": "OT-DMZ-North",
"code": "OT-DMZ-NORTH",
"zone_type": "DMZ",
"is_air_gapped": false
},
"system": {
"id": "b2c3d4e5-...",
"name": "SCADA-Production",
"code": "SCADA-OIL-01",
"criticality_level": "CRITICAL"
},
"location": {
"id": "a1b2c3d4-...",
"name": "North-Site",
"code": "PLT-NORTH"
},
"credentials_count": 2,
"pending_tasks_count": 1,
"is_active": true,
"created_at": "2024-01-15T08:00:00Z",
"created_by": "admin@contoso.com"
}Shortcut endpoint — get asset details without knowing the full hierarchy path.
GET /api/v1/acme-corp/assets/d4e5f6a7-b8c9-0123-defa-123456789012
Authorization: Bearer {access_token}
X-Request-ID: {uuid}Response 200: Same as full hierarchy GET — includes zone, system, and location context.
Use case:
When you have an asset UUID (e.g. from a checkout record or task)
and don't need to navigate the full hierarchy to get details.
Blazor Portal uses this for quick asset lookup from task views.
Update asset. Admin only. Only provided fields are updated.
PATCH /api/v1/acme-corp/locations/.../assets/d4e5f6a7-...
Authorization: Bearer {admin_token}
Content-Type: application/json
X-Request-ID: {uuid}{
"description": "Updated: Primary SCADA server — firmware updated to v3.2",
"os_version": "10.0.17763.5122",
"specification": {
"cpu": "Intel Xeon E5-2680",
"ram_gb": 64,
"storage": "2x 500GB SSD RAID1",
"firmware": "3.2.0"
}
}Response 200: Updated asset object.
Special rule for rotation_method change:
{
"rotation_method": "WINRM",
"rotation_method_change_reason": "Asset now network-connected — switching to automated rotation"
}rotation_method_change_reason is recommended when changing rotation method.
SIEM: asset.updated (INFO) or asset.rotation_method_changed (WARN)
Deactivate asset. Admin only. Soft delete.
DELETE /api/v1/acme-corp/locations/.../assets/d4e5f6a7-...
Authorization: Bearer {admin_token}
X-Request-ID: {uuid}Response 204: Asset deactivated.
Response 409 — Active checkout exists:
{
"error": {
"code": "HAS_ACTIVE_CHECKOUTS",
"message": "Asset has active checkout. Revoke it before deactivation.",
"active_checkout_id": "c3d4e5f6-..."
}
}Response 409 — Active tasks exist:
{
"error": {
"code": "HAS_ACTIVE_TASKS",
"message": "Asset has IN_PROGRESS tasks. Complete or cancel them first.",
"active_task_count": 1
}
}SIEM: asset.deactivated (WARN)
Update asset online/offline status. Admin or Rotation Agent service account.
PATCH /api/v1/acme-corp/locations/.../assets/d4e5f6a7-.../status
Authorization: Bearer {access_token}
Content-Type: application/json
X-Request-ID: {uuid}{
"is_online": true,
"last_seen_at": "2024-01-15T08:00:00Z"
}Response 200:
{
"id": "d4e5f6a7-...",
"code": "SRV-OT-001",
"is_online": true,
"last_seen_at": "2024-01-15T08:00:00Z",
"rotation_triggered": false
}Behavior on status change:
is_online: false → true:
✓ Asset marked online
✓ Worker checks for ROTATION_PENDING credentials
✓ If found: rotation tasks re-queued to RabbitMQ
✓ rotation_triggered: true in response
SIEM: asset.online (INFO)
is_online: true → false:
✓ Asset marked offline
✓ Any AUTO rotation tasks paused (moved to SCHEDULED_MANUAL logic)
SIEM: asset.offline (WARN)
List password policies for the tenant.
GET /api/v1/acme-corp/password-policies
Authorization: Bearer {access_token}
X-Request-ID: {uuid}Response 200:
{
"items": [
{
"id": "uuid",
"name": "DEFAULT",
"is_system": true,
"min_length": 16,
"max_length": 64,
"require_uppercase": true,
"require_lowercase": true,
"require_digits": true,
"require_special": true,
"exclude_ambiguous": true,
"history_count": 10,
"max_age_days": null,
"is_active": true
},
{
"id": "uuid",
"name": "LEGACY",
"is_system": true,
"min_length": 8,
"max_length": 32,
"require_uppercase": true,
"require_lowercase": true,
"require_digits": true,
"require_special": false,
"exclude_ambiguous": true,
"history_count": 5,
"max_age_days": 90,
"is_active": true
},
{
"id": "uuid",
"name": "HIGH_SECURITY",
"is_system": true,
"min_length": 32,
"max_length": 64,
"require_uppercase": true,
"require_lowercase": true,
"require_digits": true,
"require_special": true,
"exclude_ambiguous": true,
"history_count": 20,
"max_age_days": 30,
"is_active": true
}
],
"total": 3,
"page": 1,
"page_size": 20,
"total_pages": 1
}Create a custom password policy. Admin only.
POST /api/v1/acme-corp/password-policies
Authorization: Bearer {admin_token}
Content-Type: application/json
X-Request-ID: {uuid}{
"name": "SCADA-Legacy-PLC",
"description": "For older PLCs that don't support special characters",
"min_length": 10,
"max_length": 20,
"require_uppercase": true,
"require_lowercase": true,
"require_digits": true,
"require_special": false,
"allowed_special_chars": null,
"excluded_chars": "0O1lI",
"exclude_ambiguous": true,
"history_count": 8,
"max_age_days": 60
}Response 201: Created policy object.
SIEM: policy.created (INFO)
Update a custom policy. Admin only. System policies (is_system = true) cannot be modified.
Response 409 — System policy:
{
"error": {
"code": "SYSTEM_POLICY_IMMUTABLE",
"message": "System policies cannot be modified. Create a custom policy instead."
}
}SIEM: policy.updated (WARN)
Deactivate a custom policy. Admin only. System policies cannot be deactivated.
Response 409 — In use:
{
"error": {
"code": "POLICY_IN_USE",
"message": "Policy is assigned to active maintenance schedules.",
"schedules_count": 3
}
}SIEM: policy.deactivated (WARN)
GET /locations List all locations
GET /locations/{id} Location details
GET /locations/{id}/systems Systems in location
GET /locations/{id}/systems/{id} System details
GET /locations/{id}/systems/{id}/zones Zones in system
GET /locations/{id}/systems/{id}/zones/{id} Zone details
GET /locations/{id}/systems/{id}/zones/{id}/assets Assets in zone
GET /locations/{id}/systems/{id}/zones/{id}/assets/{id} Asset details
GET /assets/{id} Asset shortcut (no path)
GET /password-policies List policies
- API-Overview — conventions and error format
- API-Credentials — credential management for assets
- API-Maintenance — task and schedule management
- Database-Assets-DB — full schema reference
- Security-Authorization-Model — scope-based access
- Workflow-Rotation-Task — how asset status affects rotation