Assets API¶
Enterprise feature
The Assets API is available on Enterprise plans. Compare plans to find the right fit for your team.
The Assets API lets you manage equipment records, track asset status, record service history, submit meter readings, and transfer assets between locations. Use it to integrate asset data with your CMMS, ERP, or IoT platforms.
Endpoints summary¶
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /api/v1/assets | assets:read | List assets |
GET | /api/v1/assets?id={id} | assets:read | Get a single asset |
POST | /api/v1/assets | assets:write | Create an asset |
PUT | /api/v1/assets?id={id} | assets:write | Update an asset |
PATCH | /api/v1/assets?id={id} | assets:write | Update asset status |
GET | /api/v1/assets?id={id}&sub=service_history | assets:read | Service history |
POST | /api/v1/assets?id={id}&sub=service | assets:service | Create a service record |
POST | /api/v1/assets?id={id}&sub=meter_reading | assets:meter | Submit a meter reading |
POST | /api/v1/assets?id={id}&sub=transfer | assets:transfer | Transfer an asset |
List assets¶
GET /api/v1/assets
Scope: assets:read
Returns a paginated list of assets.
Query parameters¶
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by status (e.g., Active, In Maintenance) |
asset_type_id | integer | Filter by asset type |
condition | string | Filter by asset condition |
location_id | integer | Filter by location where the asset is installed |
ownership_type | string | Filter by ownership type (e.g., company-owned, leased) |
search | string | Search by asset name, tag, or serial number |
created_after | string | Filter assets created after this date (ISO 8601 format) |
created_before | string | Filter assets created before this date (ISO 8601 format) |
page | integer | Page number (default: 1) |
per_page | integer | Results per page (default: 50, max: 100) |
Example request¶
curl -X GET "https://fsmnavigator.com/api/v1/assets?status=Active&per_page=50" \
-H "X-API-Key: YOUR_API_KEY"
Example response¶
{
"data": [
{
"asset_id": 123,
"asset_tag": "AST-000123",
"asset_name": "Rooftop HVAC Unit #3",
"asset_type_id": 5,
"asset_type_name": "HVAC Unit",
"status": "Active",
"location_id": 87,
"location_name": "Main Office — Acme Corp",
"assigned_to": 45,
"assigned_to_name": "Alex Johnson",
"serial_number": "HVAC-2025-04821",
"model": "ClimateMax 5000",
"manufacturer": "CoolTech Industries",
"purchase_date": "2025-06-15",
"purchase_cost": 12500.00,
"warranty_expiry": "2028-06-15",
"notes": "Installed on building rooftop, zone B",
"created_at": "2025-08-15T09:00:00Z",
"updated_at": "2026-01-10T14:30:00Z"
}
],
"pagination": {
"page": 1,
"per_page": 50,
"total": 1,
"total_pages": 1
},
"request_id": "a1b2c3d4e5f6"
}
Get a single asset¶
GET /api/v1/assets?id={id}
Scope: assets:read
Retrieves full details for one asset.
Example request¶
Example response¶
{
"data": {
"asset_id": 123,
"asset_tag": "AST-000123",
"asset_name": "Rooftop HVAC Unit #3",
"asset_type_id": 5,
"asset_type_name": "HVAC Unit",
"status": "Active",
"location_id": 87,
"location_name": "Main Office — Acme Corp",
"assigned_to": 45,
"assigned_to_name": "Alex Johnson",
"serial_number": "HVAC-2025-04821",
"model": "ClimateMax 5000",
"manufacturer": "CoolTech Industries",
"purchase_date": "2025-06-15",
"purchase_cost": 12500.00,
"warranty_expiry": "2028-06-15",
"notes": "Installed on building rooftop, zone B",
"created_at": "2025-08-15T09:00:00Z",
"updated_at": "2026-01-10T14:30:00Z"
},
"request_id": "a1b2c3d4e5f6"
}
Create an asset¶
POST /api/v1/assets
Scope: assets:write
Creates a new asset record. The asset_tag is auto-generated in AST-NNNNNN format — do not include it in your request.
Request body¶
| Field | Type | Required | Description |
|---|---|---|---|
asset_name | string | Yes | Descriptive name for the asset |
asset_type_id | integer | Yes | ID of the asset type |
serial_number | string | No | Manufacturer serial number |
model | string | No | Model name or number |
manufacturer | string | No | Manufacturer name |
purchase_date | string | No | Purchase date (YYYY-MM-DD) |
purchase_cost | number | No | Purchase cost |
status | string | No | Initial status (default: Active) |
location_id | integer | No | Location where the asset is installed |
assigned_to | integer | No | Technician responsible for this asset |
notes | string | No | Additional notes |
Example request¶
curl -X POST "https://fsmnavigator.com/api/v1/assets" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"asset_name": "Lobby Printer MFP-200",
"asset_type_id": 5,
"serial_number": "MFP200-2026-04821",
"model": "MFP-200",
"manufacturer": "PrintCo",
"purchase_date": "2026-02-01",
"purchase_cost": 2499.99,
"location_id": 87,
"notes": "Second floor lobby"
}'
Example response 201 Created¶
{
"success": true,
"message": "Asset created successfully",
"data": {
"asset_id": 124,
"asset_tag": "AST-000124",
"asset_name": "Lobby Printer MFP-200"
},
"request_id": "a1b2c3d4e5f6"
}
Update an asset¶
PUT /api/v1/assets?id={id}
Scope: assets:write
Updates one or more fields on an existing asset. Only include the fields you want to change.
Example request¶
curl -X PUT "https://fsmnavigator.com/api/v1/assets?id=123" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"asset_name": "Rooftop HVAC Unit #3 (Upgraded)",
"assigned_to": 45
}'
Example response¶
{
"success": true,
"message": "Asset updated successfully",
"data": {
"asset_id": 123,
"asset_name": "Rooftop HVAC Unit #3 (Upgraded)",
"status": "Active"
},
"request_id": "a1b2c3d4e5f6"
}
Update asset status¶
PATCH /api/v1/assets?id={id}
Scope: assets:write
Changes the status of an asset. Only valid transitions are allowed — see status transitions below.
Request body¶
| Field | Type | Required | Description |
|---|---|---|---|
status | string | Yes | New status value |
Example request¶
curl -X PATCH "https://fsmnavigator.com/api/v1/assets?id=123" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "In Maintenance"
}'
Example response¶
{
"success": true,
"message": "Asset status updated to In Maintenance",
"data": {
"asset_id": 123,
"status": "In Maintenance",
"previous_status": "Active"
},
"request_id": "a1b2c3d4e5f6"
}
Status transitions¶
Not every status change is permitted. The table below shows allowed transitions:
| From status | Allowed transitions |
|---|---|
| Active | Idle, In Maintenance, In Transit, Retired, Lost, Non-Compliant, Decommissioned |
| Idle | Active, In Maintenance, In Transit, Retired, Decommissioned, Lost |
| In Maintenance | Active, Idle, Retired, Decommissioned |
| Pending Install | Active, Idle, In Transit, Non-Compliant |
| In Transit | Active, Idle, Pending Install |
| Lost | Active, Retired, Decommissioned |
| Non-Compliant | Active, Idle, In Maintenance, Retired, Decommissioned |
| Decommissioned | (terminal — no transitions) |
| Retired | Active, Decommissioned |
Tip
Use the PATCH method for status-only updates. To change other fields along with the status, use PUT instead.
Service history¶
GET /api/v1/assets?id={id}&sub=service_history
Scope: assets:read
Returns a paginated list of service records for an asset.
Query parameters¶
| Parameter | Type | Description |
|---|---|---|
page | integer | Page number (default: 1) |
per_page | integer | Results per page (default: 50) |
Example request¶
curl -X GET "https://fsmnavigator.com/api/v1/assets?id=123&sub=service_history" \
-H "X-API-Key: YOUR_API_KEY"
Example response¶
{
"data": [
{
"service_id": 1,
"asset_id": 123,
"task_id": 456,
"service_type": "preventive_maintenance",
"description": "Quarterly filter replacement and system check",
"resolution_notes": "Replaced air filters, cleaned condenser coils",
"technician_id": 45,
"service_date": "2026-02-15",
"service_started_at": "2026-02-15T09:00:00Z",
"service_completed_at": "2026-02-15T11:30:00Z",
"next_service_due": "2026-05-15",
"meter_reading_at_service": 12450,
"labor_hours": 2.5,
"service_cost": 350.00,
"is_warranty_work": false,
"warranty_claim_number": null,
"parts_used_summary": "2x HEPA filters, 1x belt",
"created_at": "2026-02-15T11:35:00Z"
}
],
"pagination": {
"page": 1,
"per_page": 50,
"total": 1,
"total_pages": 1
},
"request_id": "a1b2c3d4e5f6"
}
Create a service record¶
POST /api/v1/assets?id={id}&sub=service
Scope: assets:service
Logs a service event against an asset.
Request body¶
| Field | Type | Required | Description |
|---|---|---|---|
service_type | string | Yes | Type of service — see service types |
description | string | Yes | Description of the service performed |
service_date | string | Yes | Date of service (YYYY-MM-DD) |
service_cost | number | No | Cost of the service |
technician_id | integer | No | Technician who performed the service |
resolution_notes | string | No | Notes on the resolution or outcome |
labor_hours | number | No | Hours of labor spent |
is_warranty_work | boolean | No | Whether the service is covered by warranty |
warranty_claim_number | string | No | Warranty claim reference number |
Service types¶
| Value | Description |
|---|---|
repair | Corrective repair |
inspection | Routine or ad-hoc inspection |
preventive_maintenance | Scheduled preventive maintenance |
installation | Initial installation |
decommission | Removal from service |
meter_read | Meter reading during service |
warranty_claim | Service under warranty |
calibration | Instrument or device calibration |
upgrade | Hardware or firmware upgrade |
relocation | Physical relocation of the asset |
Example request¶
curl -X POST "https://fsmnavigator.com/api/v1/assets?id=123&sub=service" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"service_type": "preventive_maintenance",
"description": "Quarterly HVAC filter replacement",
"service_date": "2026-02-15",
"service_cost": 350.00,
"technician_id": 45,
"resolution_notes": "Replaced filters, system running normally",
"labor_hours": 2.5
}'
Example response 201 Created¶
{
"success": true,
"message": "Service record created successfully",
"data": {
"service_id": 1,
"asset_id": 123,
"service_type": "preventive_maintenance"
},
"request_id": "a1b2c3d4e5f6"
}
Submit a meter reading¶
POST /api/v1/assets?id={id}&sub=meter_reading
Scope: assets:meter
Records a meter reading for an asset.
Prerequisite: configure meters first
Meters must be set up for the asset through the web dashboard before readings can be submitted via the API. If no meter exists for the given meter_id, the API returns a 400 error with the message "Meter not found or does not belong to this asset".
Request body¶
| Field | Type | Required | Description |
|---|---|---|---|
meter_id | integer | Yes | ID of the meter (configured in the dashboard) |
reading_value | number | Yes | Current meter reading |
reading_date | string | Yes | Date of the reading (YYYY-MM-DD) |
Example request¶
curl -X POST "https://fsmnavigator.com/api/v1/assets?id=123&sub=meter_reading" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"meter_id": 1,
"reading_value": 12450,
"reading_date": "2026-02-15"
}'
Transfer an asset¶
POST /api/v1/assets?id={id}&sub=transfer
Scope: assets:transfer
Initiates a transfer of an asset to a different location.
Request body¶
| Field | Type | Required | Description |
|---|---|---|---|
to_location_id | integer | Yes | Destination location ID |
transfer_reason | string | No | Reason for the transfer |
transfer_date | string | No | Date of transfer (YYYY-MM-DD) |
Example request¶
curl -X POST "https://fsmnavigator.com/api/v1/assets?id=123&sub=transfer" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to_location_id": 22,
"transfer_reason": "Relocating to new branch office"
}'
Example response¶
{
"success": true,
"message": "Asset transfer initiated successfully",
"data": {
"transfer_id": 1,
"asset_id": 123,
"from_location_id": 87,
"to_location_id": 22,
"status": "Completed"
},
"request_id": "a1b2c3d4e5f6"
}
Asset statuses¶
Assets follow a lifecycle with nine defined statuses:
| Status | Description |
|---|---|
| Active | In regular use |
| Idle | Not currently in use but available |
| In Maintenance | Undergoing scheduled or unscheduled maintenance |
| Pending Install | Awaiting installation at a location |
| In Transit | Being moved between locations |
| Lost | Cannot be located; under investigation |
| Non-Compliant | Fails compliance or certification requirements |
| Decommissioned | Permanently removed from service (terminal) |
| Retired | Reached end of useful life (terminal) |
Error responses¶
See Error codes for the full reference. Common asset-specific errors:
| HTTP code | Error | Description |
|---|---|---|
400 | validation_failed | Missing required fields or invalid data |
400 | invalid_status_transition | The requested status change is not allowed from the current status |
400 | meter_not_found | Meter does not exist or does not belong to this asset |
404 | not_found | Asset ID does not exist |
403 | feature_not_available | Enterprise plan required |
Related guides¶
- Endpoints overview — all available endpoints
- Authentication — API key setup
- Jobs API — link jobs to assets
- Managing assets — web dashboard guide
- Asset lifecycle — status transitions explained