Usage
1) Overview
Endpoints
GET /lce/api/device_classes(filters optional)GET /lce/api/device_classes/{device_class_identifier}(ID, GUID, or name)POST /lce/api/device_classes(create or update, keyed by GUID)DELETE /lce/api/device_classes/{device_class_identifier}(ID, GUID, or name)GET /lce/api/icons(the icons that can be assigned)GET /lce/api/device_classes/{device_class_identifier}/iconPUT /lce/api/device_classes/{device_class_identifier}/icon(assign or unassign)
The Device Classes API lists, creates, updates and deletes device classes. No other platform API
authors device classes, so until now a PowerPack that needed one had to write the
master.definitions_dev_classes table directly. This API replaces those direct database writes
with validated, audited changes that keep the device class’s PowerPack revision up to date.
A device class is what discovery assigns a device to, and what Dynamic Applications are aligned with:
Discovery matches a device against the identifiers of the device classes (
class_identifier_1,class_identifier_2,discovery_qualifierand the agent identifiers) to decide which device class it belongs toDynamic Applications are aligned with a device class through its
class_type, a number allocated by the platform when the device class is created
Important
A device class is keyed by its GUID, not its id. A device class authored on one system,
for example as part of a PowerPack, keeps its GUID on every other system it is installed on,
while its id and class_type are allocated locally and differ from system to system.
POST therefore creates or updates by guid: see 6) Creating and updating device classes.
Query parameters
The query parameters behave as they do in the Dynamic Applications API, which documents them in full.
pretty (GET + POST)
All endpoints that return device classes support a pretty boolean query parameter. Defaults
to true.
pretty=trueEnums are serialized as their string names (
"device_type": "COMPONENT")
pretty=falseEnums are serialized as their integer values (
"device_type": 2)
Note
Regardless of pretty, request payloads accept enums as either integers or string names
(case-insensitive).
fields and exclude (GET + POST)
fields is an optional comma-separated allowlist of the fields to include in the
response, and exclude an optional comma-separated blocklist of the fields to remove from
it. When both are provided, fields is applied first, then exclude. On POST they only
apply to the entities returned with retrieve=true.
Return only the identifiers of every device class:
fields=id,guid,class_name,descriptionLeave out the system-specific fields:
exclude=id,class_type,last_edited
fields and exclude affect response serialization only. A path that does not exist is
ignored (no error). validation_errors is always included when present, whatever fields
and exclude specify.
retrieve (POST only)
POST /lce/api/device_classes supports a retrieve boolean query parameter. Defaults to
false.
retrieve=true: the response includes anentitieslist with each device class as it is stored after the request, in payload order. This is how to read back theid,guidandclass_typeallocated to a new device class.retrieve=false: the response includes only theresultslist.
commit (POST + DELETE)
POST /lce/api/device_classes and DELETE /lce/api/device_classes/{device_class_identifier}
support a commit boolean query parameter. Defaults to true.
commit=true: the changes are committed.commit=false: the request runs exactly as it would otherwise, validation included, and is then rolled back, so nothing is changed. The response is the one the committed request would have returned. Combine it withretrieve=trueonPOSTto preview the resulting device classes, or use it onDELETEto check whether a device class can be deleted.
require_all_filters and filter[...] (GET list only)
GET /lce/api/device_classes accepts filters of the forms:
filter[<field>][<operator>]=<value>
filter[<field>][not][<operator>]=<value>
The supported operators are is, contains, gt (single value only), lt (single
value only) and search (single value only, not negatable). Values may be comma-separated to
express multi-value matching, and for is the special value null (case-insensitive) is a
SQL NULL check on the fields that accept null, such as pp_guid.
When multiple filters are provided, require_all_filters controls how they are combined:
require_all_filters=true: all filters must match (AND logic). This is the default.require_all_filters=false: any filter may match (OR logic).
Every stored field of a device class can be filtered on: id, guid, class_name,
description, category (by id), device_type, is_snmp, class_identifier_1,
class_identifier_2, discovery_qualifier, agent_identifier_1, agent_identifier_2,
root_device, weight, tier_id, image, pp_guid, class_type and
last_edited. category_name is not a stored field and cannot be filtered
on.
Note
Unlike the other listing endpoints of this service, filters are optional. With no
filter[...] parameter, GET /lce/api/device_classes lists every device class. When
filters are provided and match nothing, the response is 404; with no filters, an empty
system returns 200 with an empty list.
limit and offset (GET list only)
GET /lce/api/device_classes pages through the device classes, ordered by id:
limit: the maximum number of device classes to return. Defaults to all of them.offset: the number of matching device classes to skip. Defaults to0.
Both must be non-negative integers; anything else is rejected with 400. An empty value, such
as limit=, is the same as leaving the parameter out. Paging applies after
the filters, and a page past the last match is an empty device_classes list rather than a
404, whether or not filters are provided. For example, the second page of 100:
GET /lce/api/device_classes?limit=100&offset=100
3) The device class
A device class is stored in master.definitions_dev_classes. The API names its fields rather
than exposing the column names, several of which are misspelled or misleading in the table.
Field |
Type |
Column |
Required / default |
Description |
|---|---|---|---|---|
|
integer |
|
read-only |
The numeric id of the device class on this system. Allocated by the database; it is not portable between systems. |
|
GUID |
|
generated when omitted |
The identity of the device class: 32 hexadecimal characters, in either case (many device classes shipped with the platform have lowercase GUIDs). The value is kept as provided, and lookups by GUID ignore case. It cannot change once the device class exists. See 6) Creating and updating device classes. |
|
string (1 to 64) |
|
required on create |
The class of the device class, typically the vendor or platform, such as |
|
string (1 to 64) |
|
required on create |
The description of the device class, typically the model or type, such as
|
|
integer |
|
required on create |
The id of the device category the device class belongs to. A payload may provide the id, the GUID or the exact name of the category. See Categories. |
|
enum |
|
|
Whether the device class describes physical, virtual or component devices. See Device types. |
|
boolean |
|
|
Whether devices of the device class are discovered over SNMP. See Identifier rules. |
|
string (0 to 255) |
|
|
The first identifier discovery matches devices against: the sysObjectID of an SNMP device class, or the first class identifier of a component device class. |
|
string (0 to 255) |
|
|
The second identifier discovery matches devices against: the second class identifier of
a component device class, or the value the |
|
string (0 to 255) |
|
|
The OID whose value must equal |
|
string (0 to 255) |
|
|
The first identifier agent discovery matches devices against. |
|
string (0 to 255) |
|
|
The second identifier agent discovery matches devices against. |
|
boolean |
|
|
Whether devices of the device class are the root of a component tree. |
|
integer (1 to 10) |
|
|
The precedence of the device class when several device classes match a device. |
|
integer (0 or more) |
|
|
The device class tier the device class belongs to: the id of a row of
|
|
string (1 to 32) |
|
|
The legacy PNG image file of the device class. Its icon is set with its own endpoint, see 8) Device class icons. |
|
GUID or |
|
|
The GUID of the PowerPack the device class belongs to, in either case. It must be the GUID of a PowerPack installed on the system. |
|
integer |
|
read-only |
The number Dynamic Applications are aligned with. Allocated when the device class is created and never changed. See Class types. |
|
string or |
|
read-only |
When the device class was last edited, as an ISO 8601 timestamp such as
|
|
string or |
(from the category) |
read-only |
The name of the category the device class belongs to, for display. |
|
array |
(none) |
read-only |
Only present on a device class whose stored values fail validation. See 10) Validation & error responses. |
String values have leading and trailing whitespace removed. A field the model does not define is rejected with 422, and text that cannot be stored as latin1 is rejected with 422.
Note
The platform shows a device class by its name: its class_name and description
joined by " | ", such as Microsoft | Windows Server 2019. The name is not a field of
the device class, but it is what the name of the results of POST and DELETE
contains, and it is accepted wherever a device class identifier is. Names are not unique:
several device classes can share a class and description, told apart by their identifiers.
See 4) Identifying a device class.
Device types
device_type is stored in the virtual column as an integer. It is serialized by name with
pretty=true (the default) and by value with pretty=false, and either is accepted in a
payload:
Name |
Value |
Meaning |
|---|---|---|
|
|
A physical device, typically discovered by its sysObjectID. |
|
|
A virtual device, created rather than discovered. |
|
|
A component device, discovered by a Dynamic Application of its parent device. |
Class identifiers
The identifiers are what discovery matches a device against to choose its device class. What each one means depends on the kind of device class:
SNMP device class (
is_snmptrue):class_identifier_1is the sysObjectID devices are matched against. To tell apart devices that share a sysObjectID, a discovery qualifier can be added:discovery_qualifieris an OID, andclass_identifier_2the value it must have.Component device class (
device_typeCOMPONENT):class_identifier_1andclass_identifier_2are the class identifiers the discovering Dynamic Application reports.Agent discovery:
agent_identifier_1andagent_identifier_2are matched against what the agent reports.
All of them default to an empty string. Note the column names: class_identifier_2 is stored
in identifyer_3, and discovery_qualifier in identifyer_2.
For example, an SNMP device class qualified by the value of sysDescr:
{
"class_name": "Cisco Systems",
"description": "Catalyst 9300",
"category": "Network",
"device_type": "PHYSICAL",
"is_snmp": true,
"class_identifier_1": "1.3.6.1.4.1.9.1.2494",
"discovery_qualifier": "1.3.6.1.2.1.1.1.0",
"class_identifier_2": "Catalyst 9300"
}
Identifier rules
The identifiers must be consistent with the kind of device class. These are the rules of the platform’s own device class editor, and a device class that breaks one is rejected with 422:
A
COMPONENTdevice class cannot haveis_snmptrue.A
PHYSICALdevice class withis_snmptrue must have a numeric OID as itsclass_identifier_1(such as1.3.6.1.4.1.9.1.2494, a leading dot is allowed), unlessagent_identifier_1is set.On such a device class, when
discovery_qualifierorclass_identifier_2is set,discovery_qualifiermust be a numeric OID.A device class that is neither SNMP nor a component must have an empty
class_identifier_1.
The rules are checked against the complete result of a request, so a stored device class that breaks one is rejected on every update, whatever field the update changes, until the payload fixes it. Every broken rule is listed in the error message.
Categories
Every device class belongs to a device category (master.definitions_dev_cats), such as
Servers or Network. In a payload, category accepts any of:
the id of the category, as an integer or a string of digits (
901or"901")the GUID of the category (its
family_guid), in either case, such as"B3A8C1E0D0F4C1A2B3C4D5E6F7A8B9C0"the exact name of the category, such as
"Servers"
A response always returns category as the id, together with the read-only category_name.
The category’s GUID is stored with the device class (family_guid) and kept in step whenever
the category changes.
A request is rejected with 422 when no category matches, or when the name matches several categories (category names are not unique); provide the id or the GUID of the category instead.
Note
The id of a category is local to the system, like the id of a device class. When copying a
device class to another system, set category to the GUID or the name of the category
rather than sending the retrieved id, which may name a different category there, or none.
category_name is read-only and is discarded from a payload, so it cannot be used to set
the category.
Class types
class_type is what Dynamic Applications are aligned with, and what devices record as their
device class. It is allocated by the service when a device class is created, as the next number
after the highest class_type in use, and it never changes afterwards. Concurrent creations
wait for one another rather than allocating the same number.
class_type is read-only: it is returned by every read, and discarded from every payload. A
device class keeps its guid across systems but not its class_type.
4) Identifying a device class
GET and DELETE on /lce/api/device_classes/{device_class_identifier} accept any of:
the numeric id, such as
5001. A numeric identifier is treated as an id, unless it is a 32-digit GUID.the GUID, such as
1F2E3D4C5B6A79881F2E3D4C5B6A7988, in either casethe name: the class and description joined by
" | ", such asMicrosoft | Windows Server 2019
The same applies to GET and PUT on /lce/api/device_classes/{device_class_identifier}/icon.
Important
Requests that change a device class only accept an exact name.
DELETE /lce/api/device_classes/{device_class_identifier} and
PUT /lce/api/device_classes/{device_class_identifier}/icon accept an id, a GUID or an
exact name, and are never fuzzy matched, so a typo cannot select another device class. A name
without an exact match returns 404:
{
"error": "Device Class Not Found",
"matches": [],
"message": "No device class found named exactly: Microsoft | Windows Server 2091",
"success": false
}
The GET endpoints still match names approximately, as described below.
A name is looked up by exact match first. When exactly one device class has the name, it is
used. Names are not unique, and when several device classes have the name, the response is
404 with their GUIDs in matches; use one of them instead:
{
"error": "Device Class Not Found",
"matches": [
"2A3B4C5D6E7F80912A3B4C5D6E7F8091",
"a7c3e9f1b5d2486c9e0f1a2b3c4d5e6f"
],
"message": "Several device classes are named 'Cisco Systems | Catalyst 9300'. Provide the GUID of the device class instead. Their GUIDs are in the matches field",
"success": false
}
On the GET endpoints, when there is no exact match and the name is at most 64 characters
long, it is matched approximately, and a confident fuzzy match is used. When the
fuzzy match is not confident, the response is 404 with the closest names in matches:
{
"error": "Device Class Not Found",
"matches": [
"Microsoft | Windows Server 2019",
"Microsoft | Windows Server 2022"
],
"message": "Device Class name is too ambiguous. There were multiple Device Classes that matched. Please provide a more specific name. Provided name: Microsoft Windows Server. Similar matches found in matches field",
"success": false
}
A name longer than 64 characters (after removing surrounding whitespace) is only looked up by
exact match, and returns 404 with no matches when there is none: No device class found
named exactly: <name>.
Note
A name is used as-is in the path, URL-encoded as usual. It contains spaces and a |:
Microsoft | Windows Server 2019 is Microsoft%20%7C%20Windows%20Server%202019. A name
may also contain a /, as hundreds of the platform’s device classes do (such as
3Com | 3Com NB:G crew dualwide w/Ae); the path accepts it. Encoding it as %2F makes no
difference, as the server decodes the path before routing it. The one exception is a name
that ends in /icon, which the path cannot tell apart from the icon endpoints of section 8:
address such a device class by its id or GUID. Prefer the GUID in automation: it is exact,
unique and portable.
5) Retrieving device classes
GET /lce/api/device_classes
Lists the device classes, ordered by id. With no filter[...] parameter every device class is
listed; with filters, only the device classes that match.
{
"device_classes": [
{
"agent_identifier_1": "",
"agent_identifier_2": "",
"category": 901,
"category_name": "Servers",
"class_identifier_1": "1.3.6.1.4.1.311.1.1.3.1.3",
"class_identifier_2": "",
"class_name": "Microsoft",
"class_type": 5001,
"description": "Windows Server 2019",
"device_type": "PHYSICAL",
"discovery_qualifier": "",
"guid": "1F2E3D4C5B6A79881F2E3D4C5B6A7988",
"id": 5001,
"image": "_generic_unknown.png",
"is_snmp": true,
"last_edited": "2026-01-05T10:00:00",
"pp_guid": "6450441E71B0EB1933D18A6C6252CF28",
"root_device": false,
"tier_id": 0,
"weight": 1
}
]
}
GET /lce/api/device_classes/{device_class_identifier}
Returns one device class, by id, GUID or name (see 4) Identifying a device class), as a single
object in the same form as an entry of device_classes.
Reads never fail because of stored data. A device class written outside this API can hold values
that fail validation, such as an empty description; it is returned as stored, with a
validation_errors list describing each problem:
"validation_errors": [
{"field": "description", "message": "String should have at least 1 character"}
]
A retrieved device class is a valid payload
Every device class returned by a GET (or in the entities of a POST) can be sent
straight back to POST /lce/api/device_classes. The read-only fields category_name,
class_type, last_edited and validation_errors are discarded from payloads, and the
other fields are compared with what is stored, so sending back an unchanged device class writes
nothing.
To change a device class, retrieve it, edit the fields that need to change, and post it back. A
device class with validation_errors is rejected with 422 until the invalid values are
corrected in the payload.
6) Creating and updating device classes
POST /lce/api/device_classes
Creates or updates one or more device classes. The request body is any of:
a single device class object
an array of device class objects
an object with a
device_classesarray, which is the formGET /lce/api/device_classesreturns
The request must be sent as JSON with a Content-Type of application/json.
GUID-keyed upsert
Each device class of the payload is matched to a stored device class by its guid:
Payload |
Result |
|---|---|
|
Updates that device class. Its stored GUID is kept, and returned, whatever the case of
the payload’s. Only the fields provided are applied, merged with the
stored values, and only the fields whose value actually changes are written. Any |
|
Creates a device class with that GUID, kept in the case provided. Any |
no |
Creates a device class with a generated GUID. |
|
Rejected with 400. A device class is not updated by id: provide the |
The GUID is the key of a device class and its id is local to a system, so a provided id
never selects or changes anything: a device class copied from another system keeps its GUID but
not its id.
class_name, description and category are required to create a device class; every
other field has a default (see the table in section 3). An update needs only the guid and the
fields that change:
{
"guid": "1F2E3D4C5B6A79881F2E3D4C5B6A7988",
"weight": 10
}
The whole payload is handled in a single transaction. Every device class is validated before any is written, and if any device class fails, nothing is written.
Validation rules
Beyond the type and range of each field, a device class must satisfy, against the complete result (the stored values updated with the payload):
Its identifiers are consistent with its kind. See Identifier rules.
Its category exists.
categorymust resolve to exactly one category (see Categories).Its tier exists.
tier_id, when not0(“No Tier”), must be the id of a row ofmaster.definitions_dev_class_tiers.Its PowerPack exists.
pp_guid, when notnull, must be the GUID of a PowerPack installed on the system.Its text can be stored. Every string must be encodable as latin1.
Its GUIDs are unique in the payload. The same
guidmay not appear twice, compared without regard to case (400).
Device classes may share a class_name and description, as they do on the platform; the
name is not a uniqueness rule.
A rule that fails rejects the whole request with 422 (400 for a duplicate GUID), naming the device class and the rule.
PowerPack revisions and the audit log
Every device class that is created or changed is recorded in the audit log, such as
User 'em7admin' added a Device Class named 'Acme | Gadget Component', ID: 5004. The revision
of each PowerPack whose device classes change is incremented, by the number of its device classes
that changed. A device class moved from one PowerPack to another increments both. A PowerPack
that is no longer installed is skipped, so a device class whose PowerPack was removed can still be
updated and deleted.
A device class that is posted unchanged writes nothing: it is not audited, it does not increment a
revision, and its last_edited is not updated. Its entry in results has "new": false,
like an update.
Response
{
"results": [
{
"guid": "7C1D9E2B4A6F48B1A3C5D7E9F0B2C4D6",
"id": 5004,
"name": "Acme | Gadget Component",
"new": true
}
],
"success": true
}
results holds one entry per device class, in payload order: its id, guid, name
and whether it is new. With retrieve=true, the response also holds an entities list
with each device class as stored, in the same order.
7) Deleting a device class
DELETE /lce/api/device_classes/{device_class_identifier}
Deletes a device class, identified by id, GUID or name (see 4) Identifying a device class).
{
"result": {
"guid": "3B4C5D6E7F8091A23B4C5D6E7F8091A2",
"id": 5003,
"name": "Acme | Widget Component"
},
"success": true
}
Important
A device class that is in use cannot be deleted. When devices belong to the device class,
or Dynamic Applications are aligned with it (both through its class_type), the request is
refused with 409 and a references object listing what still uses it:
{
"error": "Device Class In Use",
"message": "Device class 'Cisco Systems | Catalyst 9300' cannot be deleted while it is in use: 1 device(s) belong to it and 1 Dynamic Application(s) are aligned to it",
"references": {
"devices": 1,
"dynamic_applications": [
{
"guid": "0F1E2D3C4B5A69780F1E2D3C4B5A6978",
"id": 1207,
"name": "Cisco: Catalyst Inventory"
}
]
},
"success": false
}
devices is the number of devices of the device class, and dynamic_applications the
id, guid and name of each Dynamic Application aligned with it. Reassign or delete
the devices and unalign the Dynamic Applications before deleting the device class.
Note
This is stricter than the platform’s own device class editor, which refuses a deletion only when devices belong to the device class, and silently unaligns its Dynamic Applications. This API also refuses while Dynamic Applications are aligned, so that an alignment is never removed as a side effect of a deletion.
Deleting a device class also deletes its icon assignment (its row in
master_ap2.dev_class_icon) and its legacy fallback icon mapping (its row in
master.definitions_dev_class_svg_icons), invalidates the platform’s device class cache (the
ent_device_class entry of master.cache_data), as the platform’s editor does, records the
deletion in the audit log and increments the revision of its PowerPack, unless that PowerPack is
no longer installed.
The device class cache is invalidated on deletion only. Creating and updating a device class leave it alone, as the platform’s device class editor does.
With commit=false, the deletion is validated, the response is the one a committed deletion
would return (including a 409), and nothing is deleted. This is how to check whether a device
class can be deleted.
8) Device class icons
The icon of a device class is not one of its fields: it is an assignment in
master_ap2.dev_class_icon, keyed by the device class’s GUID, made through three endpoints of
their own. The image field is the legacy PNG image file name, not the icon.
GET /lce/api/iconslists the icons that can be assignedGET /lce/api/device_classes/{device_class_identifier}/iconreads the icon of a device classPUT /lce/api/device_classes/{device_class_identifier}/iconassigns or unassigns it
Together with the device class endpoints, this lets a device class be created and given its icon
entirely through this service. Assigning an icon does exactly what the GraphQL
setDeviceClassIcon mutation does, which remains an equivalent alternative.
Note
Creating icons is not part of this API. An icon must already exist to be assigned. Upload
new icons with the GraphQL createIcon mutation, which validates and compresses the SVG.
Listing icons
GET /lce/api/icons lists the icons in master_ap2.icons, ordered by name. The optional
search query parameter keeps only the icons whose name contains it, ignoring case. It is
matched literally: % and _ are not wildcards. Surrounding whitespace is ignored, so a blank
search lists every icon. size
is the size of the icon in bytes:
{
"icons": [
{ "id": "ckcwaww0000000widgetcomponent1", "name": "Widget", "size": 42 },
{ "id": "ckcwaww0000000windowsserver01", "name": "Windows Server", "size": 42 }
]
}
Reading the icon of a device class
GET /lce/api/device_classes/{device_class_identifier}/icon identifies the device class by id,
GUID or name (see 4) Identifying a device class) and returns:
{
"device_class": {
"guid": "1F2E3D4C5B6A79881F2E3D4C5B6A7988",
"id": 5001,
"name": "Microsoft | Windows Server 2019"
},
"fallback_icon": { "id": "A1B2C3D4E5F60718293A4B5C6D7E8F90", "name": "Server" },
"icon": { "id": "ckcwaww0000000windowsserver01", "name": "Windows Server" }
}
iconis the icon assigned to the device class (master_ap2.dev_class_icon), ornullwhen none is assigned.fallback_iconis the legacy icon of the device class (master.definitions_dev_class_svg_iconsjoined tomaster.definitions_default_svg_icons), which the platform shows when no icon is assigned, ornull. It is reported for information only: this API never changes it, except that deleting the device class removes it.
Icons are assigned by GUID, so a device class without a GUID is rejected with 422.
Assigning an icon
PUT /lce/api/device_classes/{device_class_identifier}/icon takes a body naming the icon by its
id or its exact name:
{ "icon": "Windows Server" }
or {"icon": null} to unassign the icon. Like setDeviceClassIcon, it replaces the
assignment of the device class and records the change in the audit log. It does not increment
the revision of the device class’s PowerPack, and it leaves fallback_icon as it is. It
supports commit=false, which validates the change and rolls it back.
Unlike setDeviceClassIcon, which always rewrites the assignment, assigning the icon a device
class already has, or unassigning when no icon is assigned, changes nothing and writes no audit
entry. The response is the same.
The response holds the icons of the device class after the change, in the same form as the
GET:
{
"result": {
"device_class": {
"guid": "1F2E3D4C5B6A79881F2E3D4C5B6A7988",
"id": 5001,
"name": "Microsoft | Windows Server 2019"
},
"fallback_icon": { "id": "A1B2C3D4E5F60718293A4B5C6D7E8F90", "name": "Server" },
"icon": { "id": "ckcwaww0000000windowsserver01", "name": "Windows Server" }
},
"success": true
}
An icon is looked up by id first, then by exact name. When several icons share the name, the
request is rejected with 422 and the message lists their ids; pass the id instead. An icon
that does not exist is also rejected with 422. The body must be sent as JSON with a
Content-Type of application/json (415 otherwise, as for POST). Malformed JSON is
rejected with 400 Invalid JSON payload provided, and JSON that is not an object with an
icon that is a non-empty string or null with 400 Invalid Icon Request.
Important
PUT /lce/api/device_classes/{device_class_identifier}/icon requires the DEV_CLASS_EDIT
access hook, which is what the setDeviceClassIcon mutation checks. It is not the
SYS_CUSTOM_DEV_CLASS_PAGE hook that creating, updating and deleting device classes
require, so a user can be allowed to do one without the other.
9) Examples
Every example uses the same Skylar One session as every other endpoint in this service. Replace
$SL1_HOST and $SL1_COOKIE with your host and session cookie.
Listing device classes
Every device class:
curl -sS -b "$SL1_COOKIE" "https://$SL1_HOST/lce/api/device_classes"
The component device classes whose class contains Acme, returning only their identifiers:
curl -sS -g -b "$SL1_COOKIE" \
"https://$SL1_HOST/lce/api/device_classes?filter[device_type][is]=COMPONENT&filter[class_name][contains]=Acme&fields=id,guid,class_name,description"
{
"device_classes": [
{
"class_name": "Acme",
"description": "Widget Component",
"guid": "3B4C5D6E7F8091A23B4C5D6E7F8091A2",
"id": 5003
}
]
}
-g stops curl from interpreting the [ and ] of the filters.
Retrieving one device class
By GUID:
curl -sS -b "$SL1_COOKIE" \
"https://$SL1_HOST/lce/api/device_classes/3B4C5D6E7F8091A23B4C5D6E7F8091A2"
By name, URL-encoded:
curl -sS -b "$SL1_COOKIE" \
"https://$SL1_HOST/lce/api/device_classes/Acme%20%7C%20Widget%20Component"
{
"agent_identifier_1": "",
"agent_identifier_2": "",
"category": 902,
"category_name": "Component",
"class_identifier_1": "acme_widget",
"class_identifier_2": "",
"class_name": "Acme",
"class_type": 5003,
"description": "Widget Component",
"device_type": "COMPONENT",
"discovery_qualifier": "",
"guid": "3B4C5D6E7F8091A23B4C5D6E7F8091A2",
"id": 5003,
"image": "_generic_unknown.png",
"is_snmp": false,
"last_edited": "2026-01-05T10:00:00",
"pp_guid": null,
"root_device": false,
"tier_id": 0,
"weight": 1
}
Creating a device class
Create a component device class in the Component category, by category name, and read it back
with retrieve=true to learn its allocated class_type:
curl -sS -X POST "https://$SL1_HOST/lce/api/device_classes?retrieve=true" \
-H "Content-Type: application/json" \
-b "$SL1_COOKIE" \
-d '{
"class_name": "Acme",
"description": "Gadget Component",
"category": "Component",
"device_type": "COMPONENT",
"class_identifier_1": "acme_gadget",
"pp_guid": "6450441E71B0EB1933D18A6C6252CF28"
}'
{
"entities": [
{
"agent_identifier_1": "",
"agent_identifier_2": "",
"category": 902,
"category_name": "Component",
"class_identifier_1": "acme_gadget",
"class_identifier_2": "",
"class_name": "Acme",
"class_type": 5004,
"description": "Gadget Component",
"device_type": "COMPONENT",
"discovery_qualifier": "",
"guid": "7C1D9E2B4A6F48B1A3C5D7E9F0B2C4D6",
"id": 5004,
"image": "_generic_unknown.png",
"is_snmp": false,
"last_edited": "2026-10-05T14:21:37",
"pp_guid": "6450441E71B0EB1933D18A6C6252CF28",
"root_device": false,
"tier_id": 0,
"weight": 1
}
],
"results": [
{
"guid": "7C1D9E2B4A6F48B1A3C5D7E9F0B2C4D6",
"id": 5004,
"name": "Acme | Gadget Component",
"new": true
}
],
"success": true
}
Align Dynamic Applications with class_type 5004. To create the device class with a known
GUID instead, for example the one it has in a PowerPack, include "guid" in the payload.
Updating a device class
Provide the guid and the fields that change. Preview the result first with commit=false:
curl -sS -X POST "https://$SL1_HOST/lce/api/device_classes?commit=false&retrieve=true" \
-H "Content-Type: application/json" \
-b "$SL1_COOKIE" \
-d '{"guid": "7C1D9E2B4A6F48B1A3C5D7E9F0B2C4D6", "class_identifier_2": "acme_gadget_v2", "weight": 5}'
Then send the same request without commit=false to apply it. The results entry has
"new": false.
Copying device classes to another system
Retrieve the device classes of a PowerPack from one system:
curl -sS -g -b "$SL1_COOKIE" \
"https://$SL1_HOST/lce/api/device_classes?filter[pp_guid][is]=6450441E71B0EB1933D18A6C6252CF28" \
-o device_classes.json
The retrieved id values can stay in the file: the target system ignores them and matches
each device class by its GUID.
Replace each category id with the category’s name or GUID (see
Categories), then post the file to the other system, where the PowerPack must
be installed. Each device class is created with its original GUID, or updated if that GUID is
already there:
curl -sS -X POST "https://$OTHER_HOST/lce/api/device_classes" \
-H "Content-Type: application/json" \
-b "$OTHER_COOKIE" \
-d @device_classes.json
Deleting a device class
Check that the device class can be deleted, then delete it:
curl -sS -X DELETE -b "$SL1_COOKIE" \
"https://$SL1_HOST/lce/api/device_classes/7C1D9E2B4A6F48B1A3C5D7E9F0B2C4D6?commit=false"
curl -sS -X DELETE -b "$SL1_COOKIE" \
"https://$SL1_HOST/lce/api/device_classes/7C1D9E2B4A6F48B1A3C5D7E9F0B2C4D6"
Giving a device class an icon
Find the icon:
curl -sS -b "$SL1_COOKIE" "https://$SL1_HOST/lce/api/icons?search=windows"
{
"icons": [
{ "id": "ckcwaww0000000windowsserver01", "name": "Windows Server", "size": 42 }
]
}
Assign it by id, or by its exact name, then read it back:
curl -sS -X PUT "https://$SL1_HOST/lce/api/device_classes/1F2E3D4C5B6A79881F2E3D4C5B6A7988/icon" \
-H "Content-Type: application/json" \
-b "$SL1_COOKIE" \
-d '{"icon": "ckcwaww0000000windowsserver01"}'
curl -sS -b "$SL1_COOKIE" \
"https://$SL1_HOST/lce/api/device_classes/1F2E3D4C5B6A79881F2E3D4C5B6A7988/icon"
Unassign it, so the platform shows the fallback_icon again:
curl -sS -X PUT "https://$SL1_HOST/lce/api/device_classes/1F2E3D4C5B6A79881F2E3D4C5B6A7988/icon" \
-H "Content-Type: application/json" \
-b "$SL1_COOKIE" \
-d '{"icon": null}'
10) Validation & error responses
Status codes
Status |
|
When |
|---|---|---|
400 |
|
A malformed |
400 |
|
A |
400 |
|
The |
400 |
|
The |
401 |
(authentication error) |
Missing or invalid authentication. |
403 |
|
The user lacks an access hook the endpoint requires. This body has |
404 |
|
No device class matches the identifier, several device classes share the name given (their
GUIDs are in |
409 |
|
|
415 |
|
The |
422 |
|
A device class fails validation: a missing required field, a value of the wrong type or
out of range, an unknown field, identifiers that break a rule of
Identifier rules, a category that does not resolve, a |
422 |
|
|
500 |
|
An unexpected error, such as a database failure. Nothing is written. |
Error body
{
"error": "Device Class(es) Failed Validation",
"message": "Device class 'Acme | Gadget Component' has invalid identifiers: A component device class cannot be an SNMP device class",
"success": false
}
Every error body has success, error and message. A 404 adds matches: the
closest names, the GUIDs of the device classes that share a name, or empty, and a 409 adds references.
A field that fails validation is named in the message, with nested locations joined by
" -> ":
{
"error": "Device Class(es) Failed Validation",
"message": "weight: Input should be less than or equal to 10",
"success": false
}