Asset Management
The Asset Management API provides offline-first access to equipment and device data with comprehensive filtering, sorting, and pagination capabilities.
Table of contents
Fetch Assets (Paginated)
Retrieves a paginated list of assets with advanced filtering and sorting options.
import zync.api.asset.models.GetAssetsResult
import zync.api.asset.models.ZyncAssetSortAndFilter
import zync.api.asset.models.ZyncAssetSortBy
import zync.api.common.filter.ZyncSortType
val sortAndFilter = ZyncAssetSortAndFilter(
sortType = ZyncSortType.Descending,
sortBy = ZyncAssetSortBy.AssetName,
keyword = "equipment",
isActive = true
)
when (val result = zync.asset.fetchAssets(
sortAndFilter = sortAndFilter,
page = 1,
pageSize = 20
)) {
is GetAssetsResult.Success -> {
val assets = result.data
val currentPage = result.currentPage
val totalPages = result.totalPages
val totalRecords = result.totalRecords
val isPartialData = result.isPartialData
println("Fetched ${assets.size} assets (page $currentPage of $totalPages)")
if (isPartialData) {
println("Data from cache - may be incomplete")
}
}
is GetAssetsResult.Failure -> {
println("Error: ${result.error.message}")
}
}
import ZuperSync
let sortAndFilter = ZyncAssetSortAndFilter(
sortType: .descending,
sortBy: .assetName,
keyword: "equipment",
isActive: true
)
switch onEnum(of: await zync.asset.fetchAssets(
sortAndFilter: sortAndFilter,
page: 1,
pageSize: 20
)) {
case .success(let success):
let assets = success.data
let currentPage = success.currentPage
let totalPages = success.totalPages
let isPartialData = success.isPartialData
print("Fetched \(assets.count) assets (page \(currentPage) of \(totalPages))")
if isPartialData {
print("Data from cache - may be incomplete")
}
case .failure(let failure):
print("Error: \(failure.error.message)")
}
Parameters
| Parameter | Type | Description |
|---|---|---|
sortAndFilter | ZyncAssetSortAndFilter | Comprehensive filter and sort options |
page | Int | Page number (1-based) |
pageSize | Int | Number of assets per page |
ZyncAssetSortAndFilter Options
| Property | Type | Description |
|---|---|---|
sortType | ZyncSortType | Sort direction (Ascending/Descending/DEFAULT) |
sortBy | ZyncAssetSortBy | Field to sort by (AssetCode, AssetName, WarrantyExpiryDate, CreatedDate) |
keyword | String? | Search keyword for asset name or code |
category | String? | Filter by asset category UID |
assetStatus | String? | Filter by asset status |
assetCode | String? | Filter by asset code |
createdDate | String? | Filter by creation date |
customField | ZyncFilterByCustomField? | Filter by custom field values |
customer | ZyncFilterModule? | Filter by customer UID |
organization | ZyncFilterModule? | Filter by organization UID |
property | ZyncFilterModule? | Filter by property UID |
serialNumbers | List<String>? | Filter by serial numbers |
warrantyExpiryDateRange | ZyncFilterDateRange? | Filter by warranty expiry date range |
filterOrphanedAssets | Boolean? | Filter orphaned assets (not linked to customer/property) |
populateInspectionForm | Boolean? | Include inspection form details |
uid | List<String>? | Filter by specific asset UIDs |
isActive | Boolean? | Filter by active status |
Return Value: GetAssetsResult
Success Case:
data: List ofZyncAssetobjectscurrentPage: Current page numbertotalPages: Total number of pages availabletotalRecords: Total number of assets across all pagesisPartialData:trueif data is from cache (may be incomplete),falseif from API
Failure Case:
error:ZyncErrorwith error details
Get Asset Detail
Retrieves comprehensive details for a specific asset, including purchase information, warranty details, parts, inspection forms, custom fields, and attachments.
import zync.api.asset.models.GetAssetResult
when (val result = zync.asset.getAssetDetail(
assetUid = "550e8400-e29b-41d4-a716-446655440000"
)) {
is GetAssetResult.Success -> {
val asset = result.data
val lastSynced = result.lastSyncedAt
val syncStatus = result.syncStatus
println("Asset: ${asset.assetName}")
println("Code: ${asset.assetCode}")
println("Status: ${asset.assetStatus}")
println("Serial Number: ${asset.serialNumber}")
println("Category: ${asset.assetCategory?.categoryName}")
println("Customer: ${asset.customer?.fullName}")
println("Property: ${asset.property?.propertyName}")
println("Warranty Expiry: ${asset.warrantyExpiryDate}")
println("Parts: ${asset.parts.size}")
println("Custom Fields: ${asset.customFields.size}")
println("Attachments: ${asset.attachments.size}")
if (syncStatus == ZyncDataSyncStatus.AGED) {
println("Note: Data is older than 5 minutes. Last synced: $lastSynced")
}
}
is GetAssetResult.Failure -> {
println("Error: ${result.error.message}")
}
}
import ZuperSync
switch onEnum(of: await zync.asset.getAssetDetail(
assetUid: "550e8400-e29b-41d4-a716-446655440000"
)) {
case .success(let success):
let asset = success.data
let lastSynced = success.lastSyncedAt
let syncStatus = success.syncStatus
print("Asset: \(asset.assetName)")
print("Code: \(asset.assetCode)")
print("Status: \(asset.assetStatus.rawValue)")
print("Serial Number: \(asset.serialNumber ?? "N/A")")
print("Category: \(asset.assetCategory?.categoryName ?? "N/A")")
print("Customer: \(asset.customer?.fullName ?? "N/A")")
print("Property: \(asset.property?.propertyName ?? "N/A")")
print("Warranty Expiry: \(asset.warrantyExpiryDate ?? "N/A")")
print("Parts: \(asset.parts.count)")
print("Custom Fields: \(asset.customFields.count)")
print("Attachments: \(asset.attachments.count)")
if syncStatus == .aged {
print("Note: Data is older than 5 minutes. Last synced: \(lastSynced)")
}
case .failure(let failure):
print("Error: \(failure.error.message)")
}
Parameters
| Parameter | Type | Description |
|---|---|---|
assetUid | String | Unique identifier of the asset |
Return Value: GetAssetResult
Success Case:
data:ZyncAssetDetailobject with comprehensive asset informationsyncStatus:ZyncDataSyncStatus- Indicates data freshness (NONEfor fresh data,AGEDfor data older than 5 minutes,OUTDATED_RECORDfor stale data)lastSyncedAt:String- ISO-8601 formatted timestamp of when this record was last synced from the server
Failure Case:
error:ZyncErrorwith error details
Asset Data Models
ZyncAsset (List Item)
Basic asset information returned in paginated lists:
| Property | Type | Description |
|---|---|---|
assetUid | String | Unique identifier |
assetCode | String | Asset code |
assetName | String | Asset name |
assetImage | String? | Asset image URL |
assetStatus | ZyncAssetStatus | Asset status enum |
isActive | Boolean | Active status |
assetCategory | ZyncAssetCategory? | Asset category |
assetLocation | ZyncAddress? | Asset location address |
serialNumber | String? | Serial number |
warrantyExpiryDate | String? | Warranty expiry date |
customer | ZyncAssetCustomer? | Associated customer info |
property | ZyncAssetProperty? | Associated property info |
organization | ZyncAssetOrganization? | Associated organization info |
inspectionForm | ZyncAssetInspectionForm? | Inspection form details |
ZyncAssetDetail (Full Detail)
Comprehensive asset information including all related data:
| Property | Type | Description |
|---|---|---|
assetUid | String | Unique identifier |
assetCode | String | Asset code |
assetName | String | Asset name |
assetImage | String? | Asset image URL |
assetStatus | ZyncAssetStatus | Asset status enum |
assetDescription | String? | Asset description |
isActive | Boolean | Active status |
assetCategory | ZyncAssetCategory? | Asset category |
assetLocation | ZyncAddress? | Asset location address |
billingAddress | ZyncAddress? | Billing address |
ownedByCustomer | Boolean | Ownership flag |
serialNumber | String? | Serial number |
purchaseDate | String? | Purchase date |
purchasePrice | Double? | Purchase price |
residualPrice | Double? | Residual value |
warrantyExpiryDate | String? | Warranty expiry date |
placedInService | String? | Service placement date |
usefulLife | ZyncAssetUsefulLife? | Useful life configuration |
customerUid | String? | Customer UID |
customer | ZyncCustomer? | Full customer details |
propertyUid | String? | Property UID |
property | ZyncProperty? | Full property details |
organizationUid | String? | Organization UID |
organization | ZyncOrganization? | Full organization details |
parentAssetUid | String? | Parent asset UID |
parentAsset | ZyncParentAsset? | Parent asset details |
createdByUid | String? | Creator UID |
createdBy | User? | User who created the asset |
parts | List<ZyncAssetPart> | Asset parts/components |
inspectionForm | ZyncAssetInspectionForm? | Inspection form details |
product | ZyncAssetProduct? | Associated product |
customFields | List<ZyncFormField> | Custom field values |
attachments | List<ZyncAttachment> | Asset attachments |
createdAt | String | Creation timestamp |
updatedAt | String? | Last update timestamp |
syncedAt | String? | Last sync timestamp |
ZyncAssetStatus Enum
Asset status values:
| Value | Description |
|---|---|
READY_TO_INSTALL | Ready for installation |
INSTALLED | Installed |
ONLINE | Online/operational |
OFFLINE | Offline |
NEEDS_REPAIR | Needs repair |
UNDER_SERVICE | Under service |
REMOVED | Removed |
OBSOLETE | Obsolete |
Best Practices
Pagination
Start with page 1 and use consistent page sizes across requests. Monitor the isPartialData flag to determine if data is from cache.
suspend fun loadAllAssets() {
val filter = ZyncAssetSortAndFilter(isActive = true)
var currentPage = 1
val pageSize = 50
do {
when (val result = zync.asset.fetchAssets(filter, currentPage, pageSize)) {
is GetAssetsResult.Success -> {
processAssets(result.data)
currentPage++
if (result.isPartialData) {
println("Warning: Showing cached data")
}
if (currentPage > result.totalPages) break
}
is GetAssetsResult.Failure -> {
println("Error loading page $currentPage: ${result.error.message}")
break
}
}
} while (true)
}
func loadAllAssets() async {
let filter = ZyncAssetSortAndFilter(isActive: true)
var currentPage = 1
let pageSize = 50
while true {
switch onEnum(of: await zync.asset.fetchAssets(
sortAndFilter: filter,
page: currentPage,
pageSize: pageSize
)) {
case .success(let success):
processAssets(success.data)
currentPage += 1
if success.isPartialData {
print("Warning: Showing cached data")
}
if currentPage > success.totalPages { break }
case .failure(let failure):
print("Error loading page \(currentPage): \(failure.error.message)")
break
}
}
}
Filtering & Sorting
Combine filters to find assets by customer, property, category, status, or warranty expiry. Use keyword search for name or code.
val filter = ZyncAssetSortAndFilter(
sortType = ZyncSortType.Ascending,
sortBy = ZyncAssetSortBy.WarrantyExpiryDate,
customer = ZyncFilterModule(uid = "customer-uid-123"),
assetStatus = "INSTALLED",
isActive = true,
warrantyExpiryDateRange = ZyncFilterDateRange(
fromDate = "2025-01-01",
toDate = "2025-12-31"
)
)
val result = zync.asset.fetchAssets(filter, 1, 50)
let filter = ZyncAssetSortAndFilter(
sortType: .ascending,
sortBy: .warrantyExpiryDate,
customer: ZyncFilterModule(uid: "customer-uid-123"),
assetStatus: "INSTALLED",
isActive: true,
warrantyExpiryDateRange: ZyncFilterDateRange(
fromDate: "2025-01-01",
toDate: "2025-12-31"
)
)
let result = await zync.asset.fetchAssets(
sortAndFilter: filter,
page: 1,
pageSize: 50
)
Offline-First Behavior
The Asset Management API follows an offline-first approach. Data is immediately available from cache, with background synchronization when online. Always check the
isPartialDataflag to determine data freshness.
The SDK returns cached data when offline and syncs in the background when online.
Error Handling
Always handle both Success and Failure cases. Use error.message for user-friendly messages and error.httpStatusCode for specific error handling.
when (val result = zync.asset.getAssetDetail(assetUid)) {
is GetAssetResult.Success -> {
// Handle success
}
is GetAssetResult.Failure -> {
when (result.error.httpStatusCode) {
404 -> println("Asset not found")
401 -> println("Authentication required")
else -> println("Error: ${result.error.message}")
}
}
}
switch onEnum(of: await zync.asset.getAssetDetail(assetUid: assetUid)) {
case .success(let success):
// Handle success
case .failure(let failure):
switch failure.error.httpStatusCode {
case 404:
print("Asset not found")
case 401:
print("Authentication required")
default:
print("Error: \(failure.error.message)")
}
}
Common Use Cases
Find Assets with Expiring Warranties
val expiringWarrantyFilter = ZyncAssetSortAndFilter(
sortBy = ZyncAssetSortBy.WarrantyExpiryDate,
isActive = true,
warrantyExpiryDateRange = ZyncFilterDateRange(
fromDate = "2025-01-01",
toDate = "2025-03-31"
)
)
when (val result = zync.asset.fetchAssets(expiringWarrantyFilter, 1, 50)) {
is GetAssetsResult.Success -> {
println("Assets with warranties expiring in Q1 2025: ${result.totalRecords}")
result.data.forEach { asset ->
println("${asset.assetName} (${asset.assetCode}) - Expires: ${asset.warrantyExpiryDate}")
}
}
is GetAssetsResult.Failure -> {
println("Error: ${result.error.message}")
}
}
let expiringWarrantyFilter = ZyncAssetSortAndFilter(
sortBy: .warrantyExpiryDate,
isActive: true,
warrantyExpiryDateRange: ZyncFilterDateRange(
fromDate: "2025-01-01",
toDate: "2025-03-31"
)
)
switch onEnum(of: await zync.asset.fetchAssets(
sortAndFilter: expiringWarrantyFilter,
page: 1,
pageSize: 50
)) {
case .success(let success):
print("Assets with warranties expiring in Q1 2025: \(success.totalRecords)")
success.data.forEach { asset in
print("\(asset.assetName) (\(asset.assetCode)) - Expires: \(asset.warrantyExpiryDate ?? "N/A")")
}
case .failure(let failure):
print("Error: \(failure.error.message)")
}
Filter by Status and Customer
val customerAssetsFilter = ZyncAssetSortAndFilter(
customer = ZyncFilterModule(uid = "customer-uid-123"),
assetStatus = "INSTALLED",
isActive = true
)
val result = zync.asset.fetchAssets(customerAssetsFilter, 1, 50)
let customerAssetsFilter = ZyncAssetSortAndFilter(
customer: ZyncFilterModule(uid: "customer-uid-123"),
assetStatus: "INSTALLED",
isActive: true
)
let result = await zync.asset.fetchAssets(
sortAndFilter: customerAssetsFilter,
page: 1,
pageSize: 50
)
Get Asset with Parts and Inspection Form
when (val result = zync.asset.getAssetDetail(assetUid)) {
is GetAssetResult.Success -> {
val asset = result.data
println("Asset: ${asset.assetName} (${asset.assetCode})")
println("Status: ${asset.assetStatus}")
println("Customer: ${asset.customer?.fullName}")
println("Property: ${asset.property?.propertyName}")
// Access purchase information
println("\nPurchase Info:")
println(" Date: ${asset.purchaseDate}")
println(" Price: ${asset.purchasePrice}")
println(" Warranty Expires: ${asset.warrantyExpiryDate}")
// Access parts
println("\nParts (${asset.parts.size}):")
asset.parts.forEach { part ->
println(" - ${part.productName}: ${part.quantity} units")
println(" Serial Numbers: ${part.serialNumbers.joinToString()}")
}
// Access inspection form
asset.inspectionForm?.let { form ->
println("\nInspection Form: ${form.formName}")
println(" Fields: ${form.formFields.size}")
}
// Access custom fields
println("\nCustom Fields (${asset.customFields.size}):")
asset.customFields.forEach { field ->
println(" ${field.fieldName}: ${field.fieldValue}")
}
// Access attachments
println("\nAttachments (${asset.attachments.size}):")
asset.attachments.forEach { attachment ->
println(" - ${attachment.fileName}")
}
}
is GetAssetResult.Failure -> {
println("Error: ${result.error.message}")
}
}
switch onEnum(of: await zync.asset.getAssetDetail(assetUid: assetUid)) {
case .success(let success):
let asset = success.data
print("Asset: \(asset.assetName) (\(asset.assetCode))")
print("Status: \(asset.assetStatus.rawValue)")
print("Customer: \(asset.customer?.fullName ?? "N/A")")
print("Property: \(asset.property?.propertyName ?? "N/A")")
// Access purchase information
print("\nPurchase Info:")
print(" Date: \(asset.purchaseDate ?? "N/A")")
print(" Price: \(asset.purchasePrice ?? 0)")
print(" Warranty Expires: \(asset.warrantyExpiryDate ?? "N/A")")
// Access parts
print("\nParts (\(asset.parts.count)):")
asset.parts.forEach { part in
print(" - \(part.productName ?? "N/A"): \(part.quantity) units")
print(" Serial Numbers: \(part.serialNumbers.joined(separator: ", "))")
}
// Access inspection form
if let form = asset.inspectionForm {
print("\nInspection Form: \(form.formName ?? "N/A")")
print(" Fields: \(form.formFields.count)")
}
// Access custom fields
print("\nCustom Fields (\(asset.customFields.count)):")
asset.customFields.forEach { field in
print(" \(field.fieldName): \(field.fieldValue ?? "N/A")")
}
// Access attachments
print("\nAttachments (\(asset.attachments.count)):")
asset.attachments.forEach { attachment in
print(" - \(attachment.fileName)")
}
case .failure(let failure):
print("Error: \(failure.error.message)")
}
Search by Serial Number
val serialNumberFilter = ZyncAssetSortAndFilter(
serialNumbers = listOf("SN-12345", "SN-67890"),
isActive = true
)
when (val result = zync.asset.fetchAssets(serialNumberFilter, 1, 50)) {
is GetAssetsResult.Success -> {
println("Found ${result.totalRecords} assets with specified serial numbers")
result.data.forEach { asset ->
println("${asset.assetName}: ${asset.serialNumber}")
}
}
is GetAssetsResult.Failure -> {
println("Error: ${result.error.message}")
}
}
let serialNumberFilter = ZyncAssetSortAndFilter(
serialNumbers: ["SN-12345", "SN-67890"],
isActive: true
)
switch onEnum(of: await zync.asset.fetchAssets(
sortAndFilter: serialNumberFilter,
page: 1,
pageSize: 50
)) {
case .success(let success):
print("Found \(success.totalRecords) assets with specified serial numbers")
success.data.forEach { asset in
print("\(asset.assetName): \(asset.serialNumber ?? "N/A")")
}
case .failure(let failure):
print("Error: \(failure.error.message)")
}